- [etc] passport를 이용하여 인증/인가 구현하기 (with nest)2024년 01월 18일 02시 20분 04초에 업로드 된 글입니다.작성자: @kimyu0218
passport로 인증/인가 구현하기
passport란?
직접 구현한 인증/인가 로직을 passport 라이브러리를 활용하여 대체할 것이다. passport는 node에서 사용하는 인증 라이브러리다.
이미 인증/인가를 구현했으면서 왜 passport를 도입했을까? 바로 passport가 표준화된 방식을 이용하고 있기 때문이다.
passport의 이점
- 표준화된, 다양한 인증 전략 제공 : 직접 다 구현할 필요없이 다양한 전략을 간단하게 사용할 수 있다.
- 풍부한 생태계 : 많은 곳에서 활발하게 사용되고 있기 때문에 문제가 발생했을 때 도움을 얻기 쉽다.
... @Injectable() export class JwtAuthGuard implements CanActivate { constructor(private readonly jwtService: JwtService) {} canActivate( context: ExecutionContext, ): boolean | Promise<boolean> | Observable<boolean> { const req: any = context.switchToHttp().getRequest(); const token: string | null = req.cookies.magicconch; if (!token) { throw new UnauthorizedException(ERR_MSG.JWT_NOT_FOUND); } const decoded: JwtPayloadDto = this.verifyToken(token); req.user = decoded; return true; } private verifyToken(token: string): JwtPayloadDto { try { return this.jwtService.verify(token); } catch (err: unknown) { this.handleVerificationError(err); throw err; } } ... }
위의 코드는 passport를 도입하기 전의 `JwtAuthGuard`다. 쿠키에 붙은 jwt 토큰을 검증하고, 검증된 사용자 정보를 요청 객체에 추가하여 해당 요청의 인증 상태를 확인한다.
nest에서 passport 사용하기
먼저 몇 가지 패키지를 설치해야 한다.
$ npm install --save @nestjs/passport passport passport-jwt $ npm install --save-dev @types/passport-jwt
passport의 다양한 전략들을 이용하기 위해서는 `@nestjs/passport`와 `passport`를 설치해야 한다. 앞에서 보았듯이 jwt를 이용하고 있으므로 `passport-jwt` 전략도 설치해줬다.
passport 전략 구현하기
앞서 말했듯이 passport 라이브러리는 표준화된 다양한 전략을 제공한다. passport에 다음 두 가지를 설정하여 내 프로젝트에 맞는 전략을 사용할 수 있다.
- 옵션 설정 (ex. jwt 전략의 경우, 토큰 서명에 사용되는 비밀키를 전달)
- 검증 콜백 설정
import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; ... @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor(private readonly configService: ConfigService) { // 1. passport-jwt에 필요한 옵션 전달 super({ jwtFromRequest: ExtractJwt.fromExtractors([ // req에서 jwt를 추출하는 방법 지정 (req: Request) => req.cookies.magicconch, ]), ignoreExpiration: false, // 만료 확인을 passport 모듈에 위임 secretOrKey: configService.get('JWT_SECRET_KEY'), // 토큰 서명에 사용하는 비밀키 }); } /* 2. 검증 콜백 설정 jwt-strategy를 사용하면... - 먼저 passport에서 jwt 서명을 확인하고, JSON을 디코딩한다. - 그 후 validate() 콜백이 실행되고, 반환값이 req 객체의 속성으로 추가된다. */ async validate(payload: any): Promise<JwtPayloadDto> { return { email: payload.email, providerId: payload.providerId, accessToken: payload.accessToken, }; } }
코드의 주석에서도 확인할 수 있듯이 passport가 요청 객체에서 데이터를 가져와 이를 검증하고 디코딩하는 과정을 대신 수행해준다. `AuthGuard`의 `canActivate`, `verifyToken`이 더 이상 필요하지 않다.
앞서 작성한 전략을 인증 가드에서 사용할 예정이기 때문에 다른 모듈이나 컴포넌트에서 사용할 수 있도록 공급자에 추가한다.
passport로 인증 가드 간단하게 수정하기
먼저, 앞서 작성한 전략을 인증 가드에서 사용할 예정이기 때문에 다른 모듈이나 컴포넌트에서 사용할 수 있도록 공급자에 추가해준다.
import { Module } from '@nestjs/common'; import { PassportModule } from '@nestjs/passport'; import { TypeOrmModule } from '@nestjs/typeorm'; ... import { AuthService } from './service/auth.service'; import { JwtStrategy } from './strategies/jwt.strategy'; @Module({ imports: [... PassportModule], // PassportModule 가져오기 controllers: [AuthController], providers: [... JwtStrategy], // JwtStrategy 공급자로 추가하기 ... }) export class AuthModule {}
이제 `@nestjs/passport`를 이용하여 앞서 만든 전략을 적용해보자. jwt 전략을 사용하고 있으므로 `AuthGuard`에 jwt를 넘겨주면 된다.
import { Injectable } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; @Injectable() export class JwtAuthGuard extends AuthGuard('jwt') {}
아까와 달리 매우 깔끔해진 것을 확인할 수 있다!!
참고자료
'backend' 카테고리의 다른 글
[etc] Spring REST Docs와 Swagger UI를 사용한 API 문서화 (0) 2025.01.17 [etc] access token & refresh token & JWT (0) 2024.09.22 [etc] CORS 이해하기 (Feat. *에서 탈출하기) (1) 2024.01.21 [etc] graceful shutdown으로 사용자 경험 저하 방지하기 (with docker & nest) (0) 2024.01.15 [etc] winston과 sentry로 서버가 터지는 이유 분석하기 (1) 2024.01.13 다음글이 없습니다.이전글이 없습니다.댓글