Skip to content

Commit ea54127

Browse files
committed
Feat: JWT 인증 구현 (토큰 버전 검증 제외)
1 parent 2b91e8d commit ea54127

14 files changed

Lines changed: 237 additions & 49 deletions

package-lock.json

Lines changed: 106 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"@nestjs/core": "^11.0.1",
2626
"@nestjs/platform-express": "^11.0.1",
2727
"@nestjs/typeorm": "^11.0.0",
28+
"jsonwebtoken": "^9.0.2",
2829
"mysql2": "^3.14.4",
2930
"reflect-metadata": "^0.2.2",
3031
"rxjs": "^7.8.1",
@@ -38,6 +39,7 @@
3839
"@nestjs/testing": "^11.0.1",
3940
"@types/express": "^5.0.0",
4041
"@types/jest": "^30.0.0",
42+
"@types/jsonwebtoken": "^9.0.10",
4143
"@types/node": "^22.10.7",
4244
"@types/supertest": "^6.0.2",
4345
"eslint": "^9.18.0",

src/app.controller.spec.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/app.controller.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/app.module.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { Module } from '@nestjs/common';
22
import { ConfigModule } from '@nestjs/config';
33
import { TypeOrmModule } from '@nestjs/typeorm';
4-
import { AppController } from './app.controller';
5-
import { AppService } from './app.service';
4+
import { AuthModule } from './auth/auth.module';
65

76
@Module({
87
imports: [
8+
AuthModule,
99
ConfigModule.forRoot({ isGlobal: true }),
1010
TypeOrmModule.forRoot({
1111
type: 'mysql',
@@ -15,10 +15,10 @@ import { AppService } from './app.service';
1515
password: process.env.DB_PASSWORD,
1616
database: process.env.DB_DATABASE,
1717
entities: [__dirname + '/**/*.entity{.ts,.js}'],
18-
synchronize: false,
18+
synchronize: process.env.NODE_ENnestV !== 'production',
1919
}),
2020
],
21-
controllers: [AppController],
22-
providers: [AppService],
21+
controllers: [],
22+
providers: [],
2323
})
24-
export class AppModule {}
24+
export class AppModule {}

src/app.service.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/auth.guard.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Request } from 'express';
2+
import { Observable } from 'rxjs';
3+
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
4+
import { AuthService } from './auth/auth.service';
5+
6+
@Injectable()
7+
export class AuthGuard implements CanActivate {
8+
constructor(private authService: AuthService) {}
9+
10+
canActivate(
11+
context: ExecutionContext,
12+
): boolean | Promise<boolean> | Observable<boolean> {
13+
const request = context.switchToHttp().getRequest();
14+
return this.validateRequest(request);
15+
}
16+
17+
private validateRequest(request: Request) {
18+
const authHeader = request.headers.authorization;
19+
20+
if (authHeader) {
21+
const token = authHeader.startsWith('Bearer ')
22+
? authHeader.slice(7)
23+
: null;
24+
if (token) {
25+
request.user = this.authService.verify(token);
26+
return true;
27+
}
28+
}
29+
30+
return false;
31+
}
32+
}

src/auth/auth.controller.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Controller, Get, UseGuards } from '@nestjs/common';
2+
import type { UserAuth } from '../types/userAuth.type';
3+
import { AuthUser } from '../decorators/auth-user.decorator';
4+
import { AuthGuard } from '../auth.guard';
5+
6+
@Controller('auth')
7+
export class AuthController {
8+
@UseGuards(AuthGuard)
9+
@Get('test')
10+
test(@AuthUser() userAuth: UserAuth): UserAuth {
11+
return userAuth;
12+
}
13+
}

src/auth/auth.module.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Module } from '@nestjs/common';
2+
import { AuthService } from './auth.service';
3+
import { AuthController } from './auth.controller';
4+
import authConfig from '../config/authConfig';
5+
import { ConfigModule } from '@nestjs/config';
6+
7+
@Module({
8+
imports: [ConfigModule.forFeature(authConfig)],
9+
controllers: [AuthController],
10+
providers: [AuthService],
11+
exports: [],
12+
})
13+
export class AuthModule {}

src/auth/auth.service.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import * as jwt from 'jsonwebtoken';
2+
import { Inject, Injectable, UnauthorizedException } from '@nestjs/common';
3+
import authConfig from 'src/config/authConfig';
4+
import type { ConfigType } from '@nestjs/config';
5+
import { UserAuth } from '../types/userAuth.type';
6+
7+
interface User {
8+
user_id: string;
9+
role: string;
10+
token_version: number;
11+
}
12+
13+
@Injectable()
14+
export class AuthService {
15+
constructor(
16+
@Inject(authConfig.KEY) private config: ConfigType<typeof authConfig>,
17+
) {}
18+
19+
verify(token: string): UserAuth {
20+
try {
21+
const payload = jwt.verify(token, this.config.jwtSecret) as unknown as (
22+
| jwt.JwtPayload
23+
| string
24+
) &
25+
User;
26+
27+
const { user_id, role, token_version } = payload;
28+
29+
return {
30+
userId: user_id,
31+
role,
32+
tokenVersion: token_version,
33+
};
34+
} catch (e) {
35+
throw new UnauthorizedException(e);
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)