NestJS - Guard

Server_side·2024년 2월 22일
1
post-custom-banner

Guard

Guard란 무엇일까?
공식문서를 통해 확인해 보면 CanAtivate 인터페이스를 구현하는 @Injectable() 데코레이터가 달린 클래스를 말한다.

guard는 말그대로 guard로서 어플리케이션으로 들어오는 요청에 대해 controller 단으로 요청이 도달하기 전 요청에 대한 인가/인증 등에 대한 validate를 통해 접근을 제어하며 어플리케이션을 보호하는 역할을 한다.

모든 Guard는 canAtivate 함수를 implement하게 되어 있으며, 해당 함수는 boolean값을 반환하며 true가 반환되면 통과, false가 반환되면 불통이다.
또한 canAtivate는 인수로 ExecutionContext 인스턴스를 가지며, 이를 통해 다양한 정보를 가져와 유용하게 활용이 가능하다.


Guard 적용법

아래는 accessToken이 유효하다면 해당 요청을 컨트롤러로 넘겨주고 유효하지 않다면 권한 없음을 응답으로 넘겨주도록 만든 guard 이며 passport 라이브러리를 활용하여 더 간단하게 구현한 것이다.

  • secretOrKey: 요청과 함께 넘어온 토큰이 유효한지 확인하기 위해 accessToken을 생성할 당시 넣은 비밀키와 동일한 키를 값으로 넣어줘야함
  • jwtFromRequset: 요청헤더에 있는 토큰값을 추출

유효한 토큰이라면 토큰에서 userId를 추출하여 controller 단으로 넘김

// access-token.strategy.ts
import { Injectable } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { ExtractJwt, Strategy } from "passport-jwt";

@Injectable()
export class AccessTokenStrategy extends PassportStrategy(Strategy, 'accessToken') {
  constructor() {
    super({
      secretOrKey: process.env.ACCESS_TOKEN_SECRET,
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
    })
  }

  validate(payload) {
    return { userId: payload.userId };
  }

}

위와 같이 작성한 Guard를 적용시키기 위해선 아래와 같이 적용이 필요한 controller 단의 핸들러에 붙여도 되며 controller 전체에 적용시키려면 @Controller 데코레이터와 붙여서 적용해도 된다.

  • 이때 @UseGuards 데코레이터를 활용하여 Guard를 적용
  • AuthGuard는 passport에서 제공되며 정의해놓은 전략들 중 원하는 전략을 적용
// user.controller.ts
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Controller('user')
export class UserController {
	@Get('current')
	@UseGuards(AuthGuard('accessToken'))
	async getMyData(//...) {
	//...~~~~~
	}
}

결과

Guard 통과

유효한 토큰과 함께 서버로 요청 시 guard를 통과하여 contoller 단으로 요청이 전달되어 응답을 보냄

Guard 에서 막힘

토큰이 없거나 유효하지 않은 토큰과 함께 서버로 요청 시 guard에서 막히며, unauthorized(401)을 반환


참고 문헌

NestJS 공식 문서

profile
아마도 난 백엔드 style?
post-custom-banner

0개의 댓글