반응형

다음은 이 글의 동영상 강의 입니다.

https://youtu.be/1upOqWW2zyU

 

Nestjs에서 JWT 토큰을 이용한 인증시에는 Guard를 사용합니다.

Guard는 라우팅 전에 작동하는 일종의 미들웨어입니다.

 

이전까지의 코드가 들어있는 샘플소스는 다음 github 저장소에서 받으실 수 있습니다.

https://github.com/CodeGearGit/nestjs-05-jwt

 

GitHub - CodeGearGit/nestjs-05-jwt

Contribute to CodeGearGit/nestjs-05-jwt development by creating an account on GitHub.

github.com

 

패키지 설치

프로젝트에 다음과 같이 패키지를 설치합니다.

npm i --save @nestjs/passport @types/passport-jwt

 

코드 작성

JWT 검증을 위해 JwtStrategy를 만듭니다.

auth/security/passport.jwt.strategy.ts

import { Injectable, UnauthorizedException } from "@nestjs/common";
import { ExtractJwt, Strategy, VerifiedCallback } from 'passport-jwt';
import { PassportStrategy } from "@nestjs/passport";
import { AuthService } from "../auth.service";
import { Payload } from "./payload.interface";

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy){
    constructor(private authService: AuthService){
        super({
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            ignoreExpiration: true,
            secretOrKey: 'SECRET_KEY',
        })
    }

    async validate(payload: Payload, done: VerifiedCallback): Promise<any> {
        const user = await this.authService.tokenValidateUser(payload);
        if (!user) {
            return done(new UnauthorizedException({ message: 'user does not exist' }), false);
        }

        return done(null, user);
    }
}

auth/auth.service.ts 에 tokenValidateUser를 추가합니다.

async tokenValidateUser(payload: Payload): Promise<UserDTO | undefined> {
    return await this.userService.findByFields({
        where: { id: payload.id }
    });
}

auth/auth.module.ts

- imports에 PassportModule 을 추가하고,

- providers에 JwtStrategy 를 추가합니다.

import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { JwtStrategy } from './security/passport.jwt.strategy';
import { UserRepository } from './user.repository';
import { UserService } from './user.service';

@Module({
  imports: [
    TypeOrmModule.forFeature([UserRepository]),
    JwtModule.register({
      secret: 'SECRET_KEY',
      signOptions: {expiresIn: '300s'},
    }),
    PassportModule
  ],
  exports: [TypeOrmModule],
  controllers: [AuthController],
  providers: [AuthService, UserService, JwtStrategy]
})
export class AuthModule {}

auth/security/auth.guard.ts를 만듭니다.

import { ExecutionContext, Injectable } from '@nestjs/common';
import { AuthGuard as NestAuthGuard } from '@nestjs/passport';

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

auth/auth.controller.ts에 아래와 같이 라우터를 하나 추가합니다.

@Get('/authenticate')
@UseGuards(AuthGuard)
isAuthenticated(@Req() req: Request): any { 
    const user: any = req.user;
    return user;
}

 

테스트

jwt 인증 모듈의 개발이 완료되었으므로 Postman을 이용해서 테스트를 해봅니다.

토큰이 없을 경우 다음과 같이 Unauthorized 값이 리턴됩니다.

로그인 호출을 통해 토큰 값을 받아옵니다.

토큰을 이용해 authenticate를 다시 호출합니다.

- Headers 에 다음 값을 입력합니다.

   KEY: Authorization

   VALUE : 로그인에서 받아온 토큰값

다음과 같이 결과가 나오는걸 보실 수 있습니다.

이상으로 JWT 인증하는 법에 대해 알아보았습니다.

 

최종 완료된 소스는 아래 URL에서 확인하시면 됩니다.

https://github.com/CodeGearGit/nestjs-06-jwt-auth

 

GitHub - CodeGearGit/nestjs-06-jwt-auth

Contribute to CodeGearGit/nestjs-06-jwt-auth development by creating an account on GitHub.

github.com

 

반응형

+ Recent posts