NestJS/모르는 것들

Guard, Strategy, Passport, Jwt

흰제비갈매기 2024. 6. 25. 16:02

Guard

Guard는 요청(request)을 처리하기 전에 실행되며, 주로 권한 부여(Authorization) 로직을 수행한다. Guard는 request이 특정 조건을 만족하는지 여부를 확인하고, 그렇지 않으면 request를 차단한다.

  • 역할: 요청이 보호된 리소스에 접근할 자격이 있는지 확인한다.
  • 동작 방식: 'canActivate' method를 구현하여, true를 반환하면 요청이 진행되고, false를 반환하면 요청이 차단된다.

Strategy

Strategy는 인증(Authentication) 로직을 처리한다. 다양한 인증 전략(e.g. JWT, OAuth, Local 등)을 구현할 수 있으며, Passport.js를 통해 이를 쉽게 통합할 수 있다.

  • 역할: 사용자의 자격 증명(e.g. JWT 토큰)을 확인하고 인증한다.
  • 동작 방식: 인증이 성공하면 사용자 정보를 반환하고, 실패하면 예외를 던진다.

Passport

Node.js용 인증 미들웨어이다. 다양한 인증 전략을 지원하며. NestJS에서 쉽게 사용할 수 있도록 Passport 모듈을 제공한다.

  • 역할: 다양한 인증 전략을 통합하여 사용할 수 있게 한다.
  • 동작 방식: 특정 전략을 사용하여 사용자를 인증하고, 인증 결과를 바탕으로 Guard가 요청을 처리할 수 있도록 한다.

JWT

JWT는 JSON 기반의 인증 토큰이다. 주로 client와 server 간에 인증 정보를 안전하게 전송하기 위해 사용된다.

  • 역할: 사용자 인정 정보를 포함하는 토큰을 생성하고 검증한다.
  • 동작 방식: 서버는 사용자가 로그인할 때 JWT를 생성하여 클라이언트에 전달하고, 클라이언트는 이후 요청 시 이 토큰을 포함하여 서버에 전달한다. 서버는 토큰을 검증하여 사용자를 인증한다.

동작 원리

  1. 사용자 로그인

    • 사용자가 로그인 정보를 서버에 제출
    • 서버는 사용자를 인증하고, JWT 토큰을 생성하여 클라이언트에 반환
  2. JWT 토큰을 포함한 요청

    • 클라이언트는 보호된 리소스에 접근하기 위해 JWT 토큰을 포함한 요청을 서버에 보낸다.
  3. Guard가 요청을 가로채고 검사

    • 요청이 서버에 도달하면, Guard가 이를 가로채고 'canActivate' method를 호출
    • 'canActivate' 메서드는 Passport를 사용하여 JWT 전략을 통해 토큰을 검증
  4. Strategy가 토큰 검증

    • JWT 전략이 토큰을 검증한다. 토큰이 유효하면 사용자 정보를 반환하고, 그렇지 않으면 예외를 던진다.
  5. Guard가 요청 허용 여부 결정

    • JWT 전략이 반환한 사용자 정보를 바탕으로 Guard가 요청을 허용할지 결정
    • 인증이 성공하면 요청이 처리되고, 실패하면 요청이 차단

// JWT Strategy
import { Strategy, ExtractJwt } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: process.env.JWT_SECRET, // 환경 변수에서 비밀 키를 가져옴
      ignoreExpiration: false, // 토큰 만료 시간을 무시하지 않음
    });
  }

  async validate(payload: any) {
    return { userId: payload.sub, username: payload.username };
  }
}


// Auth Guard
import { Injectable, ExecutionContext } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  canActivate(context: ExecutionContext) {
    return super.canActivate(context);
  }
}

// Auth Module
import { Module } from '@nestjs/common';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { JwtStrategy } from './jwt/jwt.strategy';
import { PassportModule } from '@nestjs/passport';
import { JwtModule } from '@nestjs/jwt';

@Module({
  imports: [
    PassportModule.register({ defaultStrategy: 'jwt', session: false }),
    JwtModule.register({
      secret: process.env.JWT_SECRET,
      signOptions: { expiresIn: '1y' },
    }),
  ],
  controllers: [AuthController],
  providers: [AuthService, JwtStrategy],
})
export class AuthModule {}

// Controller
import { Controller, Get, UseGuards } from '@nestjs/common';
import { JwtAuthGuard } from './auth/jwt-auth.guard';

@Controller('cats')
export class CatsController {
  @UseGuards(JwtAuthGuard)
  @Get()
  findAll() {
    return [];
  }
}

요약

  • Guard: 요청이: 보호된 리소스에 접근할 자격이 있는지 확인
  • Strategy: 사용자의 자격 증명을 확인하고 인증한다.
  • Passport: 다양한 인증 전략을 통합하여 사용할 수 있게 한다.
  • JWT: 사용자 인증 정보를 포함하는 토큰을 생성하고 검증