본문 바로가기

Learning/NestJS

NestJS Authentication(4) jwt(수정)

[수정] member.module와 auth.module 서로 각각의 service를 providers 한 다면 종속성 오류가 난다.

아래 사이트 내용을 봐야 할거 같다.

ichi.pro/ko/nestjs-tamsaeg-nestui-modyul-siseutem-150387603343728

 

NestJS 탐색 — Nest의 모듈 시스템

주의! 이 기사는 시리즈의 2 부 : NestJS 탐색 🙌🏻입니다. 원하는 경우 여기에서 파트 1을 찾을 수 있습니다. https : // medium.

ichi.pro

 

 

jwt 하다가 환경변수 부분으로 샛길로 빠졌었다. 다시 돌아와서 ....

 

auth.module

import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { MemberModule } from '../member.module';
import { PassportModule } from '@nestjs/passport';
import { LocalStrategy } from './strategies/local.strategy';
import { JwtStrategy } from './strategies/jwt.strategy';
import { JwtModule } from '@nestjs/jwt';

@Module({
  imports: [
    MemberModule,
    PassportModule,
    JwtModule.register({
      secret: process.env.JWT_SECRETKEY, // env에 추가 필요 JWT_SECRETKEY: 아무거나
      signOptions: { expiresIn: '60s' }, //토큰의 만료시간 60초
    }),
  ],
  controllers: [],
  providers: [AuthService, LocalStrategy, JwtStrategy],
  exports: [AuthService],
})
export class AuthModule {}

JwtModule을 사용하게 구성한다. register에 구성 개체를 전달.

secret 값은 env 환경변수에서 가져오는것으로 변경 ( 공식 문서에서는 ts 파일에 클레스를 만들었지만 그럴경우 secret 값이 노출 되어 진다. 위험)

signOptions는 많은 항목이 있지만 우선 expiresIn의 값을 설정 한다. 토큰의 만료 시간으로 

현재는 60초를 하였다. 나중에 테스트 후 정상 확인을 하면 값을 변경할 필요가 있다 더 길게~

구성옵션은 아래 참고

github.com/auth0/node-jsonwebtoken#usage

 

auth0/node-jsonwebtoken

JsonWebToken implementation for node.js http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html - auth0/node-jsonwebtoken

github.com

아래 코드는 공식문서와는 다르지만 결론은 authService에 login클래스에 아이디를 전달해서 

로그인을 하고 생성된 토큰을 받아와서 반환 해 주는 것

  @UseGuards(LocalAuthGuard)
  @Post('/login')
  async login(@Body() logins: LoginMemberDto): Promise<Response> {
    const tokens = this.authService.login(logins.LOGIN_ID);
    return new ResponseMessage().success().body(tokens).build();
  }

 

이다음은 API의 엔드포인트에 접근 했을 경우 jwt를 요구하여 유효한지 확인하는

jwt.strategy 생성

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: false,
      secretOrKey: process.env.JWT_SECRETKEY,
    });
  }

  async validate(payload: any) {
    return { userId: payload.sub, username: payload.username };
  }
}

super 호출 시 초기화 옵션은 아래 확인

github.com/mikenicholson/passport-jwt#configure-strategy

 

mikenicholson/passport-jwt

Passport authentication using JSON Web Tokens. Contribute to mikenicholson/passport-jwt development by creating an account on GitHub.

github.com

github.com/mikenicholson/passport-jwt#extracting-the-jwt-from-the-request

 

mikenicholson/passport-jwt

Passport authentication using JSON Web Tokens. Contribute to mikenicholson/passport-jwt development by creating an account on GitHub.

github.com

jwtFromRequest:에서 JWT를 추출하는 방법을 제공합니다 Request. API 요청의 Authorization 헤더에 전달자 토큰을 제공하는 표준 접근 방식을 사용합니다. 

ignoreExpiration: 명시 적으로 false말하자면 JWT가 Passport 모듈에 만료되지 않았는지 확인하는 책임을 위임 하는 기본 설정 을 선택합니다 . 즉, 만료 된 JWT와 함께 경로가 제공되면 요청이 거부되고 401 Unauthorized응답이 전송됩니다. Passport는이를 자동으로 처리합니다.

 validate()방법은 논의 할 가치가 있습니다. jwt-strategy의 경우 Passport는 먼저 JWT의 서명을 확인하고 JSON을 디코딩합니다. 그런 다음 validate()디코딩 된 JSON을 단일 매개 변수로 전달하는 메서드 를 호출합니다 . JWT 서명이 작동하는 방식에 따라 이전에 서명하여 유효한 사용자에게 발행 한 유효한 토큰  받고 있음을 보장합니다 .

 

생성된 jwt.strategy를 auth.module에 providers에 추가를 합니다.

 

JWT에 서명 할 때 사용한 것과 동일한 비밀을 가져옴 으로써 Passport에서 수행 한 확인 단계와 AuthService에서 수행  서명 단계가 공통 비밀을 사용 하는지 확인 합니다.

 

마지막으로 JwtAuthGuard내장을 확장하는 클래스를 정의합니다 AuthGuard.

jwt-auth.guard 생성

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

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

 

보호 경로 및 JWT 전략 가드 구현

이제 보호 된 경로와 관련 가드를 구현할 수 있습니다.

app.controller.ts파일을 열고 아래와 같이 업데이트합니다.

 

  @UseGuards(LocalAuthGuard)
  @Post('/login')
  async login(@Body() logins: LoginMemberDto): Promise<Response> {
    const tokens = this.authService.login(logins.LOGIN_ID);
    return new ResponseMessage().success().body(tokens).build();
  }

  @UseGuards(JwtAuthGuard)
  @Post()
  async addMember(@Body() register: CreateMemberDto): Promise<Response> {
    try {

login을 하고 Post할경우 성공 60초가 지나면 401 에러가 난다.

 

guard 확장 

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

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  canActivate(context: ExecutionContext) {
    // Add your custom authentication logic here
    // for example, call super.logIn(request) to establish a session.
    return super.canActivate(context);
  }

  handleRequest(err, user, info) {
    // You can throw an exception based on either "info" or "err" arguments
    if (err || !user) {
      throw err || new UnauthorizedException();
    }
    return user;
  }
}

 

이부분은 구현하지 않았으니 다음에 필요시에 찾아 보자

docs.nestjs.com/security/authentication#extending-guards

 

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 Progamming), FP (Functional Programming), and FRP (Functional Reac

docs.nestjs.com

git에 해당 내용을 작업을 하였으며

퇴근 후 pull을 한 뒤에 오류나는 부분을 수정을 하자.

 

 

여기까지 작성된 내용은 수정을 하지 않고 git은 몇부분 수정을 함

github.com/dittyBox/study-nestjs

 

dittyBox/study-nestjs

Learning NestJS (nomadcoders). Contribute to dittyBox/study-nestjs development by creating an account on GitHub.

github.com

 

 

 

이전글

leannet.tistory.com/72

 

NestJS Authentication(3) 환경변수

41살 개발자로 이직이 가능한 나이는 지난것 같은... 토이 프로잭트를 한다고 하니 주변분들이 그거 돈되나 라고 물어 보신다.. 훗... 요 몇일간 현타가 왔다.... 내가 지금 새롭게 배우고 새로운게

leannet.tistory.com

 

'Learning > NestJS' 카테고리의 다른 글

INSOMNIA 사용하여 Header에 token 사용  (1) 2021.01.12
NestJS Authentication(3) 환경변수  (0) 2021.01.07
NestJS Authentication(2) jwt+환경변수  (0) 2021.01.06
NestJS Authentication(1) Login  (0) 2021.01.03
DTO (Data Transfer Object)  (0) 2021.01.02