Nest.js 백엔드 AuthGuard (인증) 가이드
Nest.js 백엔드 AuthGuard (인증) 가이드 Nest.js에서는 라는 개념을 통하여 인증을 구현하도록 권장하고 있습니다. Nest.js는 내부적으로 기반의 웹 서버를 사용하기 때문에 는 일종의 특수한 미들웨어(middleware)라고 할 수 있습니다. Express.js에서 미들웨어(middleware)란 요청(request)를 받은 이후에 응답(response)를 보내기전 별도로 구현된 로직을 타는 중간단계의 로직입니다. 아래는 Express 미들웨어의 예제입니다. ts @Injectable() export class AuthGuard implements CanActivate { // Express.js 미들웨어와 다르게 ExecutionContext라는 파라미터를 제공하여 요청으로부터 어떤 응답을 할 것인지에 대한 정보까지 들어있는 실행 컨텍스트입니다. canActivate(context: ExecutionContext): boolean { // 원하는 로직을 구현합니다. (생략) // 요청을 승인합니다. return true; } } ts @Get() @SetMetadata('public', true) async test() { return true; } ts @Injectable() export class AuthGuard implements CanActivate { constructor(private readonly reflector: Reflector) {} canActivate(context: ExecutionContext): boolean { // Reflector를 사용하여 키값에 대한 메타데이터를 추출합니다. const isPublic = this.reflector.get<boolean('public', context.getHandler()); if (isPublic) return true; else return false; } } ts @Injectable() export class AuthGuard implements CanActivate { constructor( private readonly reflector: Reflector, private readonly jwt: JwtService ) {} async canActivate(context: ExecutionContext): Promise<boolean { // Context에서 Public에 대한 메타데이터 추출 const isPublic = this.reflector.get<boolean('ISPUBLIC', context.getHandler()); // Public 메타데이터가 지정된 API의 경우 별도의 인증이 필요 없기 때문에 승인합니다. if (isPublic) { return true; } // Context에서 요청(request), 응답(response)를 추출합니다. (Express의 req, res와 동일) const req = context.switchToHttp().getRequest(); const res = context.switchToHttp().getResponse(); // 요청 쿠키에서 액세스 토큰, 리프레시 토큰을 추출합니다. const accessToken = req.cookies["액세스 토큰 쿠키 키값"]; const refreshToken = req.cookies["리프레시 토큰 쿠키 키값"]; // 엑세스 토큰이 없는 경우 if (!accessToken) { return false; } // CASE 1: 모든 토큰이 만료된 경우 if (isAccessTokenExpired(accessToken) && isRefreshTokenExpired(refreshToken)) { return false; } // CASE 2: 액세스 토큰만 만료된 경우 else if (isAccessTokenExpired(accessToken) && !isRefreshTokenExpired(refreshToken)) { // 만료된 액세스 토큰과 리프레시 토큰을 검증하여 신규 액세스 토큰을 발급합니다. const newAccessToken = renewAccessToken(accessToken, refreshToken); // 신규 액세스 토큰을 쿠키로 발급합니다. res.cookie("액세스 토큰 쿠키 키값", newAccessToken, {maxAge: 액세스토큰만료시간 }); return true; } // CASE 3: 리프레시 토큰만 만료된 경우 else if (!isAccessTokenExpired(accessToken) && isRefreshTokenExpired(refreshToken)) { // 액세스 토큰과 만료된 리프레시 토큰을 검증하여 신규 액세스 토큰을 발급합니다. const newRefreshToken = renewRefreshToken(accessToken, refreshToken); // 신규 리프레시 토큰을 쿠키로 발급합니다. res.cookie("리프레시 토큰 쿠키 키값", newRefreshToken, {maxAge: 리프레시토큰만료시간 }); return true; } // CASE 4: 모든 토큰이 유효한 경우 else { return true; } } } ts // main.ts에서 useGlobalGuards를 사용하여 전역으로 지정할 수 있습니다. async boostrap() { const app = await NestFactory.create(AppModule); app.useGlobalGuards(new AuthGuard()); } // 또는 모듈에서 APPGUARD 메타데이터를 지정하여 애플리케이션 단위로 지정할 수 있습니다. @Module({ providers: [ { provider: APPGUARD, useClass: AuthGuard } ] }) export class AppModule {} ts // 특정 모듈에서만 사용할 수 있습니다. @Module({ providers: [AuthGuard] }) export class PostsModule {} // 특정 컨트롤러에서만 사용할 수 있습니다. @Controller('cats') @UseGuards(new AuthGuard()) export class CatsController {} ts @Controller() export class AppController { @Get() @UseGuards(AuthGuard) async getTest() { return true; } } `
10 months ago