인증 (Authentication)
ASAPJS에서 인증은 TypedMiddleware를 사용해 애플리케이션에서 직접 구현합니다. 이 가이드는 JWT 기반 인증 미들웨어의 전체 구현 예시입니다.
TypedMiddleware패턴의 개념과 동작 원리는 TypedMiddleware 문서를 먼저 읽어보세요.
사전 준비
config.ts에 JWT 시크릿을 설정합니다.
// src/config.ts
auth: {
jwt_access_token_secret: process.env.JWT_SECRET || 'your-secret-key',
}Step 1: jwtMiddleware 구현
TypedMiddleware 타입을 사용하여 JWT 검증 로직을 작성합니다.
// src/middleware/jwtMiddleware.ts
import { getConfig } from '@asapjs/common';
import type { TypedMiddleware } from '@asapjs/types';
import type { NextFunction, Request, Response } from 'express';
import jwt from 'jsonwebtoken';
export interface JwtUserPayload {
[key: string]: any;
}
export const jwtMiddleware: TypedMiddleware<{ auth?: boolean }, { user: JwtUserPayload }> =
({ auth = false } = {}) =>
(req: Request, res: Response, next: NextFunction) => {
const { authorization } = req.headers;
if (!authorization) {
if (auth === true) {
return res.status(403).json({ error: true, message: 'NO Token Provided' });
}
return next();
}
const token = authorization.split(' ')[1];
const secret = (getConfig() as any).auth.jwt_access_token_secret;
jwt.verify(token, secret, (err: any, decoded: any) => {
if (err && auth === true) {
if (err.message === 'invalid signature') {
return res.status(403).json({
error: true,
message: 'invaild signature. please use vaild endpoint',
});
}
return res.status(401).json({
error: true,
message: 'Unauthorized access. Please Refresh Token',
});
}
// 검증 성공 시 req.user에 페이로드 저장
req.user = decoded;
next();
});
};Step 2: Config 등록 및 타입 선언
구현한 미들웨어를 defineRouterConfig를 통해 등록하고, 프레임워크의 전역 타입을 확장(Augmentation)합니다.
// src/config.ts
import { defineRouterConfig, type InferMiddlewareRouteOptions } from '@asapjs/router';
import { jwtMiddleware, type JwtUserPayload } from './middleware/jwtMiddleware';
// 1. 라우터 설정 정의
export const routerConfig = defineRouterConfig({
middleware: [jwtMiddleware],
});
export default {
// ... 기타 설정
router: routerConfig,
auth: {
jwt_access_token_secret: process.env.JWT_SECRET || 'your-secret-key',
},
};
// 2. 전역 타입 확장
declare module '@asapjs/router' {
// ExecuteArgs.user의 타입을 지정
interface GlobalMiddlewareContext {
user: JwtUserPayload;
}
// IOptions에 미들웨어가 요구하는 옵션(auth?: boolean)을 추가
interface GlobalRouteOptions
extends InferMiddlewareRouteOptions<typeof routerConfig.middleware> {}
}Step 3: 컨트롤러 사용
이제 모든 라우트 데코레이터에서 auth 옵션을 사용할 수 있으며, ExecuteArgs에서 user 정보를 타입 안전하게 꺼내 쓸 수 있습니다.
// src/user/controller/UserController.ts
import { RouterController, Get, Post, ExecuteArgs } from '@asapjs/router';
export default class UserController extends RouterController {
public basePath = '/users';
constructor() {
super();
this.registerRoutes();
}
@Get('/me', {
title: '내 정보 조회',
auth: true, // GlobalRouteOptions에 의해 타입 체크됨
})
public getMe = async ({ user }: ExecuteArgs) => {
// user는 JwtUserPayload 타입으로 자동 추론됨
return { user };
};
@Post('/login', {
title: '로그인',
auth: false, // 인증 없이 접근 가능
})
public login = async ({ body }: ExecuteArgs) => {
// 로그인 로직...
return { token: '...' };
};
}JWT 헬퍼
토큰 발급을 위한 유틸리티 함수 예시입니다.
// src/utils/jwt.ts
import jwt from 'jsonwebtoken';
import { getConfig } from '@asapjs/common';
export function jwtSign(payload: any, expiresIn: string = '7d'): string {
const secret = (getConfig() as any).auth.jwt_access_token_secret;
return jwt.sign(payload, secret, { expiresIn });
}에러 응답
jwtMiddleware 구현에 따라 다음과 같은 응답이 반환될 수 있습니다.
| 상황 | HTTP | 응답 |
|---|---|---|
토큰 없음 (auth: true) | 403 | { "error": true, "message": "NO Token Provided" } |
잘못된 서명 (auth: true) | 403 | { "error": true, "message": "invaild signature..." } |
만료 (auth: true) | 401 | { "error": true, "message": "Unauthorized access..." } |
auth: false | — | next() 호출, req.user는 undefined |
관련 문서
- TypedMiddleware — 커스텀 미들웨어 만들기
- 요청 라이프사이클 — 미들웨어 실행 위치
Last updated on