11import { NextFunction , Request , Response } from 'express' ;
2- import axios from 'axios' ;
32import { isUUID } from 'class-validator' ;
43import logger from '@/configs/logger.config' ;
54import pool from '@/configs/db.config' ;
6- import { DBError , InvalidTokenError } from '@/exception' ;
7- import { VELOG_API_URL , VELOG_QUERIES } from '@/constants/velog.constans ' ;
5+ import { InvalidTokenError } from '@/exception' ;
6+ import { VelogJWTPayload , User } from '@/types ' ;
87
98/**
109 * 요청에서 토큰을 추출하는 함수
@@ -22,60 +21,23 @@ const extractTokens = (req: Request): { accessToken: string; refreshToken: strin
2221 return { accessToken, refreshToken } ;
2322} ;
2423
25- /**
26- * Velog API를 통해 사용자 정보를 조회합니다.
27- * @param query - GraphQL 쿼리 문자열
28- * @param accessToken - Velog access token
29- * @throws {Error } API 호출 실패 시
30- * @returns Promise<VelogUserLoginResponse | null>
31- */
32- const fetchVelogApi = async ( query : string , accessToken : string , refreshToken : string ) => {
33- try {
34- const response = await axios . post (
35- VELOG_API_URL ,
36- { query, variables : { } } ,
37- {
38- headers : {
39- authority : 'v3.velog.io' ,
40- origin : 'https://velog.io' ,
41- 'content-type' : 'application/json' ,
42- cookie : `access_token=${ accessToken } ; refresh_token=${ refreshToken } ` ,
43- } ,
44- } ,
45- ) ;
46-
47- const result = response . data ;
48-
49- if ( result . errors ) {
50- logger . error ( 'GraphQL Errors : ' , result . errors ) ;
51- throw new InvalidTokenError ( 'Velog API 인증에 실패했습니다.' ) ;
52- }
53-
54- return result . data . currentUser || null ;
55- } catch ( error ) {
56- logger . error ( 'Velog API 호출 중 오류 : ' , error ) ;
57- throw new InvalidTokenError ( 'Velog API 인증에 실패했습니다.' ) ;
58- }
59- } ;
60-
6124/**
6225 * JWT 토큰에서 페이로드를 추출하고 디코딩하는 함수
26+ * 이건 진짜 velog 에서 사용하는 걸 그대로 가져온 함수임!
6327 * @param token - 디코딩할 JWT 토큰 문자열
64- * @returns JSON 객체로 디코딩된 페이로드
28+ * @returns { VelogJWTPayload }
6529 * @throws {Error } 토큰이 잘못되었거나 디코딩할 수 없는 경우
6630 * @example
6731 * const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U";
6832 * const payload = extractPayload(token);
6933 * // 반환값: { sub: "1234567890" }
7034 */
71- const extractPayload = ( token : string ) => JSON . parse ( Buffer . from ( token . split ( '.' ) [ 1 ] , 'base64' ) . toString ( ) ) ;
35+ const extractPayload = ( token : string ) : VelogJWTPayload => JSON . parse ( Buffer . from ( token . split ( '.' ) [ 1 ] , 'base64' ) . toString ( ) ) ;
7236
7337/**
74- * Bearer 토큰을 검증한뒤 최초 로그인이라면 Velog 사용자를 인증을, 아니라면 기존 사용자를 인증하여 user정보를 Request 객체에 담는 함수
75- * @param query - 사용자 정보를 조회할 GraphQL 쿼리
76- * @returns
38+ * Bearer 토큰을 검증한뒤 user정보를 Request 객체에 담는 인가 함수
7739 */
78- const verifyBearerTokens = ( query ?: string ) => {
40+ const verifyBearerTokens = ( ) => {
7941 return async ( req : Request , res : Response , next : NextFunction ) => {
8042 try {
8143 const { accessToken, refreshToken } = extractTokens ( req ) ;
@@ -84,23 +46,12 @@ const verifyBearerTokens = (query?: string) => {
8446 throw new InvalidTokenError ( 'accessToken과 refreshToken의 입력이 올바르지 않습니다' ) ;
8547 }
8648
87- let user = null ;
88- if ( query ) {
89- user = await fetchVelogApi ( query , accessToken , refreshToken ) ;
90- if ( ! user ) {
91- throw new InvalidTokenError ( '유효하지 않은 토큰입니다.' ) ;
92- }
93- } else {
94- const payload = extractPayload ( accessToken ) ;
95- if ( ! payload . user_id || ! isUUID ( payload . user_id ) ) {
96- throw new InvalidTokenError ( '유효하지 않은 토큰 페이로드 입니다.' ) ;
97- }
98-
99- user = ( await pool . query ( 'SELECT * FROM "users_user" WHERE velog_uuid = $1' , [ payload . user_id ] ) ) . rows [ 0 ] ;
100- if ( ! user ) {
101- throw new DBError ( '사용자를 찾을 수 없습니다.' ) ;
102- }
49+ const payload = extractPayload ( accessToken ) ;
50+ if ( ! payload . user_id || ! isUUID ( payload . user_id ) ) {
51+ throw new InvalidTokenError ( '유효하지 않은 토큰 페이로드 입니다.' ) ;
10352 }
53+
54+ const user = ( await pool . query ( 'SELECT * FROM "users_user" WHERE velog_uuid = $1' , [ payload . user_id ] ) ) . rows [ 0 ] as User ;
10455 req . user = user ;
10556 req . tokens = { accessToken, refreshToken } ;
10657
@@ -114,10 +65,8 @@ const verifyBearerTokens = (query?: string) => {
11465
11566/**
11667 * 사용자 인증을 위한 미들웨어 모음
117- * @property {Function } login - 최초 로그인 시 Velog API를 호출하는 인증 미들웨어
118- * @property {Function } verify - 기존 유저를 인증하는 미들웨어
68+ * @property {Function } verify
11969 */
12070export const authMiddleware = {
121- login : verifyBearerTokens ( VELOG_QUERIES . LOGIN ) ,
12271 verify : verifyBearerTokens ( ) ,
12372} ;
0 commit comments