JWT - Passport 사용하기

2025. 12. 22. 02:18·NestJS/개발

Passport

Passport는 Node.js 생태계에서 가장 널리 사용되는 인증(Authentication) 라이브러리 중 하나로, 이미 수많은 실무 애플리케이션에서 검증된 안정성과 확장성을 가지고 있다. NestJS에서는 @nestjs/passport 모듈을 통해 Passport를 프레임워크에 자연스럽게 통합할 수 있으며, 이를 통해 인증 로직을 Nest의 Guard, Strategy, Provider 구조에 맞게 표준화할 수 있다. Passport의 가장 큰 장점은 다양한 인증 방식을 전략(Strategy)이라는 개념으로 분리해 제공한다는 점이다. JWT, Local, OAuth 등 여러 인증 메커니즘을 동일한 패턴으로 처리할 수 있으며, @nestjs/passport는 이러한 Passport의 동작 방식을 NestJS 스타일로 래핑하여 일관되고 유지보수하기 쉬운 인증 구조를 만들 수 있게 해준다.


npm install 패키지

npm i @nestjs/passport passport passport-jwt

@nestjs/passport

  • AuthGuard('jwt'), PassportStrategy 제공
  • 실제 인증 로직은 없음

passport

  • Passport 코어 엔진
  • 전략을 실행하고 흐름을 관리함

passport-jwt

  • JWT 인증 전략
  • 토큰 추출, 서명 검증, 만료 체크 수행
  • Strategy, ExtractJwt 제공

 

 

JwtStrategy 와 JwtAuthGuard

깜짝 놀랄정도로 아주 편하다. 왜 passport를 쓰라는지 느낌이온다. 본 포스트도 공식문서를 따라가면서 정리중이다.
https://docs.nestjs.com/recipes/passport#implementing-passport-jwt

간단히 단계를 설명하자면

  • JwtStrategy 생성 - 공식문서 셋팅 그대로
  • JwtAuthGuard 생성
  • UseGuards() 데코레이터 이용해서 사용 - 끝

src/auth/에 작업을 이어 나가보자 기존에 있던 Guard는 삭제했다.

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

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: jwtConstants.secret,
    });
  }


  // 성공하면 reqeust객체에 user로 넣어줌
  async validate(payload: any) {
    return { id: payload.uuid, role: payload.role };
  }
}

 

  • jwtFromReqeust: Authorization에서 추출해서 Bearer 와 토큰 분리해서 작업을 알아서 함
  • ignoreExpriation: 기본적으로 false 해두라고 함
  • secretOrKey: 우리가 jwt 발급하면서 만들어둔 시크릿키 넣으면 됨
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class JwtGuard extends AuthGuard('jwt') {}

그리고 JwtAuthGuard를 하나 만들고 위와 같이 셋팅한다. 공식문서와 똑같다.

이 작업만 해주면 Authorization에서 뽑아서 토큰검사를 하고, 정상이면 다음 스텝 비정상이면 401 에러가 나온다.


역할 기반 검증 추가하기

커스텀 데코레이터를 하나 만든다. 이 데코레이터는 해당 라우터에 들어가는 역할을 검증하는 데코레이터이다.

import { Reflector } from '@nestjs/core';

export const Roles = Reflector.createDecorator<string[]>();

 

역할기반 가드를 하나 만들어야한다.

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
import { Roles } from './roles.decorator';

@Injectable()
export class RoleGuard implements CanActivate {
  constructor(private readonly reflector: Reflector) {}
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const roles = this.reflector.getAllAndOverride(Roles, [
      context.getHandler(),
      context.getClass(),
    ]);

    if (!roles) {
      return true;
    }

    // 권한 확인하기
    const { user } = context.switchToHttp().getRequest();

    return roles.includes(user.role);
  }
}

이제 다음 부분은 특히 신중하게 설계해야 한다. 이번 구조에서는 가드를 전역으로 등록하고, JwtAuthGuard가 먼저 실행된 뒤 RoleGuard가 이어서 실행되는 흐름을 사용한다. JwtAuthGuard는 요청에 포함된 토큰을 검증하고, 검증에 성공하면 사용자 정보를 request.user에 담는다. 그 다음 RoleGuard에서는 요청 경로와 request.user에 담긴 역할 정보를 기준으로 접근 가능 여부를 판단하여 true 또는 false를 반환한다.


여기까지 구현하면 인증과 인가에 대한 기본적인 셋업은 완료된 셈이다. 하지만 여기서 한 가지 더 고민해야 할 부분이 있다. JwtAuthGuard를 전역으로 활성화한 상태에서는 로그인과 회원가입 요청도 모두 가드를 타게 된다는 점이다.로그인은 토큰을 발급받기 전 단계이기 때문에, 이 요청까지 JWT 검증을 요구하면 로그인 자체가 불가능해진다. 따라서 실제 서비스에서 JwtAuthGuard -> RoleGuard 흐름은 유지하되, 로그인과 회원가입 같은 인증 이전 단계의 엔드포인트는 예외로 통과시켜주는 처리가 반드시 필요하다. 이를 위해 @Public() 같은 메타데이터를 활용해 특정 경로에서는 JwtAuthGuard와 RoleGuard를 건너뛰도록 설계하는 것이 일반적인 접근 방식이다.

import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { AuthService } from './auth.service';
import { jwtConstants } from './constants';
import { JwtStrategy } from './jwt.strategy';
import { APP_GUARD } from '@nestjs/core';
import { JwtAuthGuard } from './jwt.auth.guard';
import { RoleGuard } from './role.guard';

@Module({
  imports: [
    JwtModule.register({
      global: true,
      secret: jwtConstants.secret,
      signOptions: { expiresIn: '30m' }, //30분
    }),
  ],
  providers: [
  // 순서대로 가드 켜짐
    { provide: APP_GUARD, useClass: JwtAuthGuard },
    { provide: APP_GUARD, useClass: RoleGuard },
    AuthService,
    JwtStrategy,
  ],
  exports: [AuthService],
})
export class AuthModule {}

 

Public() 데코레이터 생성하기

import { SetMetadata } from '@nestjs/common';

export const IS_PUBLIC = 'isPublic';
export const Public = () => SetMetadata(IS_PUBLIC, true);

생성 한 후 @Public()이면 토큰 검사를 패스해줘야 하기 때문에 JwtAuthGuard로 간다.

import { ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { Observable } from 'rxjs';
import { IS_PUBLIC } from './public.decorator';

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  constructor(private readonly reflector: Reflector) {
    super();
  }

  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC, [
      context.getHandler(),
      context.getClass(),
    ]);

    if (isPublic) {
      return true;
    }

    return super.canActivate(context);
  }
}

참고

https://docs.nestjs.com/recipes/passport

 

Documentation | NestJS - A progressive Node.js framework

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Rea

docs.nestjs.com

 

'NestJS > 개발' 카테고리의 다른 글

실시간 채팅 서버 개발 - 01 (Redis 및 NestJS 셋팅)  (1) 2026.01.14
Redis/BullMQ 이용하여 연산 작업 따로하기  (0) 2025.12.23
JWT - 역할 기반 관리하기  (1) 2025.12.21
JWT - 토큰 활용하기  (0) 2025.12.21
JWT - 로그인 후 발급하기  (1) 2025.12.21
'NestJS/개발' 카테고리의 다른 글
  • 실시간 채팅 서버 개발 - 01 (Redis 및 NestJS 셋팅)
  • Redis/BullMQ 이용하여 연산 작업 따로하기
  • JWT - 역할 기반 관리하기
  • JWT - 토큰 활용하기
나는지토
나는지토
  • 나는지토
    안녕은헬로입니다.
    나는지토
  • 전체
    오늘
    어제
    • 분류 전체보기 (27)
      • Backend Design (1)
      • NestJS (19)
        • 개발 (9)
        • 개념과 구조 정리 (10)
      • SpringBoot (0)
      • Java (4)
        • 코테 (0)
      • PostgreSQL (2)
      • Docker (1)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    코딩테스트
    JWT
    인증 가드
    Collections
    Redis
    토큰 검사
    컨트롤러
    커서기반 조회
    ArrayList
    nestjs
    db 연결 오류
    자료구조
    역할 검사
    서비스
    nestjs/jwt
    채팅
    PostgreSQL
    조회 방식
    BullMQ
    Java
  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
나는지토
JWT - Passport 사용하기
상단으로

티스토리툴바