8. Nest.js 광부왕 게임 서버 JWT 설정

2023. 3. 3. 18:39프로젝트/게임 서버 - Nest.js

1. @types/passport-jwt, passport, passport-jwt, @nestjs/jwt, @nestjs/passport 설치

npm i -D @types/passport-jwt
npm i passport, passport-jwt, @nestjs/jwt, @nestjs/passport

2. auth module 생성

nest g mo auth

생성 된 auth.module.ts 파일 작성

  • JWT인증을 Guard로 공통된 인증 처리를 해야하기 때문에 @Global()를 적용.
  • JWT 만료 기간은 1일이다.
import { Global, Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { JwtStrategy } from './jwt.strategy';

@Global()
@Module({
  imports: [
    JwtModule.register({
      secret: process.env.JWT,
      signOptions: { expiresIn: '1d' },
    }),
  ],
  providers: [JwtStrategy],
  exports: [JwtModule],
})
export class AuthModule {}

3. src/auth/jwt.strategy.ts 생성

 

 jwtFromRequest 설정 : JWT는 Bearer token을 통해 가져온다.

ignoreExpiration 설정 :  JWT 만료 처리 strategy에서 하지 않는다.

* 밑에 Guard에서 처리 하기 때문에 무시

import { ExtractJwt, Strategy } 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(),
      ignoreExpiration: true,
      secretOrKey: process.env.JWT,
    });
  }
}

4. src/auth/jwt.guard.ts 생성

 

validateToken : 토큰 검증을 진행하고 잘못된 토큰일 경우 예외처리(401) 를 진행한다.

canActivate : 토큰 없이 접근 시 예외처리를 진행한다(401), 토큰 검증은 validateToken 함수에서 진행

 

import {
  ExecutionContext,
  Injectable,
  UnauthorizedException,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  constructor(private jwtService: JwtService) {
    super();
  }
  validateToken(token: string) {
    try {
      //관리자, 유저 분기 처리예정
      const verify = this.jwtService.verify(token, { secret: process.env.JWT });
      return verify;
    } catch (e) {
      switch (e.message) {
        case 'jwt expired':
        case 'invalid token':
        case 'jwt malformed':
        case 'jwt signature is required':
        case 'invalid signature':
          throw new UnauthorizedException();
      }
    }
  }

  canActivate(context: ExecutionContext) {
    const request = context.switchToHttp().getRequest();
    const { authorization } = request.headers;
    if (authorization === undefined) {
      throw new UnauthorizedException();
    }
    const token = authorization.replace('Bearer ', '');
    request.user = this.validateToken(token);
    return true;
  }
}

5. src/auth/jwt.payload.ts 생성

 

JWT에서 가져올수있는 데이터 Interface 작성

export interface jwtPayload {
  userIndex: string;
  status: boolean;
  accessLevel: boolean;
}

 

728x90
반응형