From 58d092536e8b284b3309898ff13adfe9929a5f4e Mon Sep 17 00:00:00 2001 From: Hyang-Dan Date: Mon, 1 Dec 2025 22:36:01 +0900 Subject: [PATCH] =?UTF-8?q?issue=20#39=20-=20Access=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=20=EB=A7=8C=EB=A3=8C=20=EC=8B=9C=20Refresh=20=ED=86=A0?= =?UTF-8?q?=ED=81=B0=EC=9C=BC=EB=A1=9C=20Access=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EA=B0=B1=EC=8B=A0=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/middleware/auth/auth.service.ts | 2 +- .../auth/guard/access-token.guard.ts | 44 ++++++++++++++++++- .../auth/guard/refresh-token.guard.ts | 44 ++++++++++++++++++- .../auth/strategy/access-token.strategy.ts | 6 ++- .../auth/strategy/refresh-token.strategy.ts | 6 +-- src/modules/account/account.controller.ts | 5 ++- 6 files changed, 96 insertions(+), 11 deletions(-) diff --git a/src/middleware/auth/auth.service.ts b/src/middleware/auth/auth.service.ts index 6e67e0b..895eb65 100644 --- a/src/middleware/auth/auth.service.ts +++ b/src/middleware/auth/auth.service.ts @@ -6,7 +6,7 @@ export class AuthService { constructor(private readonly jwtService: JwtService) {} generateTokens(payload: any) { - const accessToken = this.jwtService.sign(payload, { expiresIn: '1h' }); + const accessToken = this.jwtService.sign(payload, { expiresIn: '5s' }); const refreshToken = this.jwtService.sign({id: payload.id}, { expiresIn: '7d' }); return { accessToken, refreshToken }; diff --git a/src/middleware/auth/guard/access-token.guard.ts b/src/middleware/auth/guard/access-token.guard.ts index 9a745ee..41e2077 100644 --- a/src/middleware/auth/guard/access-token.guard.ts +++ b/src/middleware/auth/guard/access-token.guard.ts @@ -1,5 +1,45 @@ -import { Injectable } from "@nestjs/common"; +import { ExecutionContext, Injectable, UnauthorizedException } from "@nestjs/common"; +import { Reflector } from "@nestjs/core"; +import { TokenExpiredError } from "@nestjs/jwt"; import { AuthGuard } from "@nestjs/passport"; +import { IS_PUBLIC_KEY } from "src/common/decorators/public.decorator"; @Injectable() -export class JwtAccessAuthGuard extends AuthGuard('access-token') {} \ No newline at end of file +export class JwtAccessAuthGuard extends AuthGuard('access-token') { + constructor(private reflector: Reflector) { + super(); + } + + canActivate(context: ExecutionContext) { + const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [ + context.getHandler(), + context.getClass() + ]); + + if (isPublic) { + return true; + } + + return super.canActivate(context); + } + + handleRequest(err: any, user:any, info:any) { + if (info instanceof TokenExpiredError) { + throw new UnauthorizedException({ + statusCode: 401, + message: 'Access Token Expired', + code: 'AccessTokenExpired' + }); + } + + if (err || !user) { + throw new UnauthorizedException({ + statusCode: 401, + message: 'Invalid Token', + code: 'InvalidToken' + }); + } + + return user; + } +} diff --git a/src/middleware/auth/guard/refresh-token.guard.ts b/src/middleware/auth/guard/refresh-token.guard.ts index 9c5fb34..1c511a9 100644 --- a/src/middleware/auth/guard/refresh-token.guard.ts +++ b/src/middleware/auth/guard/refresh-token.guard.ts @@ -1,5 +1,45 @@ -import { Injectable } from "@nestjs/common"; +import { ExecutionContext, Injectable, UnauthorizedException } from "@nestjs/common"; +import { Reflector } from "@nestjs/core"; +import { TokenExpiredError } from "@nestjs/jwt"; import { AuthGuard } from "@nestjs/passport"; +import { IS_PUBLIC_KEY } from "src/common/decorators/public.decorator"; @Injectable() -export class JwtRefreshAuthGuard extends AuthGuard('refresh-token') {} \ No newline at end of file +export class JwtRefreshAuthGuard extends AuthGuard('refresh-token') { + constructor(private reflector: Reflector) { + super(); + } + + canActivate(context: ExecutionContext) { + const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [ + context.getHandler(), + context.getClass() + ]); + + if (isPublic) { + return true; + } + + return super.canActivate(context); + } + + handleRequest(err: any, user:any, info:any) { + if (info instanceof TokenExpiredError) { + throw new UnauthorizedException({ + statusCode: 401, + message: 'Refresh Token Expired', + code: 'RefreshTokenExpired' + }); + } + + if (err || !user) { + throw new UnauthorizedException({ + statusCode: 401, + message: 'Invalid Token', + code: 'InvalidToken' + }); + } + + return user; + } +} \ No newline at end of file diff --git a/src/middleware/auth/strategy/access-token.strategy.ts b/src/middleware/auth/strategy/access-token.strategy.ts index 3e284ec..bcc2577 100644 --- a/src/middleware/auth/strategy/access-token.strategy.ts +++ b/src/middleware/auth/strategy/access-token.strategy.ts @@ -1,4 +1,4 @@ -import { Injectable } from "@nestjs/common"; +import { Injectable, UnauthorizedException } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { PassportStrategy } from "@nestjs/passport"; import { ExtractJwt, Strategy } from "passport-jwt"; @@ -13,6 +13,10 @@ export class JwtAccessStrategy extends PassportStrategy(Strategy, "access-token" } async validate(payload: any) { + const token = ExtractJwt.fromAuthHeaderAsBearerToken(); + if (!token) { + throw new UnauthorizedException(); + } return { id: payload.id }; } } \ No newline at end of file diff --git a/src/middleware/auth/strategy/refresh-token.strategy.ts b/src/middleware/auth/strategy/refresh-token.strategy.ts index 26b5685..ba3a32b 100644 --- a/src/middleware/auth/strategy/refresh-token.strategy.ts +++ b/src/middleware/auth/strategy/refresh-token.strategy.ts @@ -13,10 +13,10 @@ export class JwtRefreshStrategy extends PassportStrategy(Strategy, 'refresh-toke }); } - async validate(req: any, payload: any) { - const token = ExtractJwt.fromAuthHeaderAsBearerToken()(req); + async validate(payload: any) { + const token = ExtractJwt.fromAuthHeaderAsBearerToken(); - if (!token) throw new UnauthorizedException(); + if (!token) throw new UnauthorizedException('Invalid Refresh Token'); return { id: payload.id, diff --git a/src/modules/account/account.controller.ts b/src/modules/account/account.controller.ts index f535fa0..12f616d 100644 --- a/src/modules/account/account.controller.ts +++ b/src/modules/account/account.controller.ts @@ -3,13 +3,13 @@ import { AccountService } from "./account.service"; import * as DTO from "./dto"; import { JwtAccessAuthGuard } from "src/middleware/auth/guard/access-token.guard"; import { Public } from "src/common/decorators/public.decorator"; +import { JwtRefreshAuthGuard } from "src/middleware/auth/guard/refresh-token.guard"; @UseGuards(JwtAccessAuthGuard) @Controller('account') export class AccountController { constructor(private readonly accountService: AccountService) {} - @Public() @Get('/') async test() { return "Test" @@ -51,7 +51,8 @@ export class AccountController { } @Public() - @Post('refresh-access-token') + @UseGuards(JwtRefreshAuthGuard) + @Get('refresh-access-token') async refreshAccessToken(@Req() req): Promise { const id = req.user.id; const newAccessToken = this.accountService.refreshAccessToken(id);