Skip to Content

jwtVerification

이 페이지에서 찾을 수 있는 것

심볼분류설명
jwtVerificationMiddleware FactoryJWT Bearer 토큰 검증 미들웨어

개요

jwtVerification은 Express 미들웨어 팩토리로, 라우트 데코레이터의 auth 옵션에 따라 JWT 토큰 검증을 수행합니다. RouterController가 등록된 모든 라우트에 내부적으로 적용하므로, 일반적인 사용에서는 직접 호출할 필요가 없습니다.

import { jwtVerification } from '@asapjs/router';

시그니처

const jwtVerification: (auth?: boolean) => (req: Request, res: Response, next: NextFunction) => void
파라미터타입기본값설명
authbooleanfalsetrue이면 유효한 Bearer 토큰이 필요합니다. false이면 토큰이 있을 경우 수락하지만 필수는 아닙니다.

동작 방식

미들웨어는 모든 요청에서 다음 로직을 실행합니다:

  1. Authorization 헤더를 읽습니다.
  2. 헤더가 없는 경우:
    • auth === trueHttpException(403, 'NO Token Provided')를 throw합니다.
    • auth === falsenext()를 호출합니다. req.user는 설정되지 않습니다.
  3. 헤더가 있는 경우, Bearer <token> 형식에서 토큰을 추출하고 config.auth.jwt_access_token_secret으로 검증합니다.
  4. 검증 성공 → 디코딩된 페이로드를 req.user에 저장하고 next()를 호출합니다.
  5. 검증 실패, auth === true → 에러 유형에 따라 응답을 전송합니다.
  6. 검증 실패, auth === falsereq.user를 설정하지 않고 next()를 호출합니다.

에러 응답 형식

시나리오HTTP 상태응답 경로바디
토큰 없음, auth: true403throw HttpExceptionerrorToResponse(){ status: 403, errorCode: 'LEGACY_HTTP_EXCEPTION', message: 'NO Token Provided' }
유효하지 않은 서명, auth: true403res.json() 직접 응답{ error: true, message: 'invaild signature...' }
만료/유효하지 않은 토큰, auth: true401res.json() 직접 응답{ error: true, message: 'Unauthorized access. Please Refresh Token' }
실패, auth: false요청 계속 진행req.userundefined

참고: 토큰 없음 케이스는 throw로 에러 파이프라인을 거쳐 { status, errorCode, message } 형식이지만, JWT 검증 실패 케이스는 res.json() 직접 응답으로 { error, message } 형식입니다. 클라이언트 에러 처리 시 두 가지 형식을 모두 고려해야 합니다.

IOptions의 auth 옵션과 연동

데코레이터의 auth 필드가 jwtVerification의 동작을 제어합니다:

import { Get, Post, ExecuteArgs } from '@asapjs/router'; // 공개 라우트 — 토큰 불필요 @Get('/posts', { title: 'List posts', auth: false, // 기본값; 생략 가능 }) async getPosts({ paging }: ExecuteArgs) { ... } // 보호된 라우트 — 유효한 Bearer 토큰 필요 @Post('/posts', { title: 'Create post', auth: true, body: CreatePostDto, }) async createPost({ body, user }: ExecuteArgs) { ... }

auth를 생략하면 기본값은 false입니다.

필수 설정

jwtVerification은 전역 설정 객체에서 시크릿을 읽습니다:

{ auth: { jwt_access_token_secret: 'your-secret-key' } }

설정은 런타임에 @asapjs/commongetConfig()를 통해 접근합니다. 키가 없으면 첫 번째 인증 요청 시점에 JWT 검증이 오류를 던집니다.

JWT 토큰 형식

클라이언트는 Bearer 방식을 사용하여 Authorization 헤더에 토큰을 전달합니다:

Authorization: Bearer <jwt-token>

미들웨어는 공백을 기준으로 분리하여 두 번째 세그먼트를 토큰 문자열로 사용합니다.

전체 컨트롤러 예제

공개 라우트(auth: false)와 보호된 라우트(auth: true)를 함께 사용하는 컨트롤러 예제입니다:

import { RouterController, Get, Post, ExecuteArgs } from '@asapjs/router'; import { HttpException } from '@asapjs/router'; import UserApplication from '../application/UserApplication'; import CreateUserDto from '../dto/CreateUserDto'; import LoginRequestDto from '../dto/LoginRequestDto'; import LoginResponseDto from '../dto/LoginResponseDto'; import UserInfoDto from '../dto/UserInfoDto'; export default class UserController extends RouterController { public tag = 'User'; public basePath = '/users'; private userService: UserApplication; constructor() { super(); this.registerRoutes(); this.userService = new UserApplication(); } // 공개 — 토큰 불필요 @Post('/register', { title: 'Register', description: 'Creates a new user account.', body: CreateUserDto, response: UserInfoDto, }) async register({ body }: ExecuteArgs) { return await this.userService.register(body as CreateUserDto); } // 공개 — 토큰 불필요 @Post('/login', { title: 'Login', description: 'Authenticates with email and password, returns a JWT.', body: LoginRequestDto, response: LoginResponseDto, }) async login({ body }: ExecuteArgs) { return await this.userService.login(body as LoginRequestDto); } // 보호된 라우트 — 유효한 Bearer 토큰 필요 @Get('/me', { title: 'Get current user', description: 'Returns the profile of the authenticated user.', auth: true, response: UserInfoDto, }) async getMe({ user }: ExecuteArgs) { if (!user?.id) { throw new HttpException(401, 'Token payload missing user id'); } return await this.userService.getUserInfo(user); } }

관련 항목

Last updated on