Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import { UserModule } from 'src/user/user.module';
import { AuthModule } from './auth/auth.module';
import { RedisModule } from './redis/redis.module';
import { GameRoomModule } from './gameRoom/gameRoom.module';
import { ChatModule } from './chat/chat.module';
import { GameModule } from './game/game.module';

@Module({
imports: [
UserModule,
AuthModule,
RedisModule,
GameRoomModule,
ChatModule,
GameModule,
TypeOrmModule.forRoot({
type: 'mysql',
host: process.env.MYSQL_HOST || 'mysql',
Expand Down
72 changes: 59 additions & 13 deletions src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,22 +76,25 @@ export class AuthController {
const accessToken = this.jwtService.sign(payload, { expiresIn: '2h' });
const refreshToken = this.jwtService.sign(payload, { expiresIn: '7d' });

// Redis 저장
await this.redisService.set(`access:${user.userEmail}`, accessToken, 3600);
await this.redisService.set(
`refresh:${user.userEmail}`,
refreshToken,
7 * 24 * 60 * 60,
);

// Refresh Token 쿠키 설정
res.cookie('refreshToken', refreshToken, {
httpOnly: true, // JavaScript로 접근 불가
secure: true, // HTTPS에서만 동작 (개발시엔 false로 설정)
httpOnly: true,
secure: true,
sameSite: 'none',
maxAge: 7 * 24 * 60 * 60 * 1000, // 7일
maxAge: 7 * 24 * 60 * 60 * 1000,
});

// 클라이언트로 토큰 반환 (새로 sign하지 말고 기존 accessToken 그대로)
return {
accessToken: `Bearer ${this.jwtService.sign(payload)}`,
accessToken: `Bearer ${accessToken}`,
};
}

Expand Down Expand Up @@ -132,7 +135,7 @@ export class AuthController {
})
@ApiResponse({
status: 200,
description: '새로운 Access Token을 발급합니다.',
description: '새로운 Access Token과 Refresh Token을 발급합니다.',
schema: {
example: {
accessToken: 'Bearer <NEW_ACCESS_TOKEN>',
Expand All @@ -153,8 +156,8 @@ export class AuthController {
@Req() req: Request,
@Res({ passthrough: true }) res: Response,
) {
const refreshToken = req.cookies['refreshToken']; // 쿠키에서 RefreshToken 읽기
if (!refreshToken) {
const oldRefreshToken = req.cookies['refreshToken']; // 쿠키에서 RefreshToken 읽기
if (!oldRefreshToken) {
throw new HttpException(
'Refresh token not found',
HttpStatus.UNAUTHORIZED,
Expand All @@ -163,26 +166,69 @@ export class AuthController {

try {
// RefreshToken 검증
const payload = this.jwtService.verify(refreshToken);
const payload = this.jwtService.verify(oldRefreshToken);

// Redis에서 RefreshToken 확인
const storedRefreshToken = await this.redisService.get(
`refresh:${payload.userEmail}`,
);

if (!storedRefreshToken || storedRefreshToken !== refreshToken) {
if (
!storedRefreshToken ||
storedRefreshToken.trim() !== oldRefreshToken.trim()
) {
throw new HttpException(
'Invalid refresh token',
HttpStatus.UNAUTHORIZED,
);
}

// 새로운 AccessToken 생성
console.log(payload);
// 새로운 AccessToken 생성 (만료 시간 1시간)
const newAccessToken = this.jwtService.sign(
{ userEmail: payload.userEmail, sub: payload.sub },
{ expiresIn: '15m' },
{
userEmail: payload.userEmail,
userId: payload.userId,
sub: payload.sub,
},
{ expiresIn: '1h' }, // 1시간
);

// 새로운 RefreshToken 생성
const newRefreshToken = this.jwtService.sign(
{
userEmail: payload.userEmail,
userId: payload.userId,
sub: payload.sub,
},

{ expiresIn: '7d' },
);

// Redis에 새로운 토큰 저장
// 기존 Redis 키 삭제
await this.redisService.del(`access:${payload.userEmail}`);
await this.redisService.del(`refresh:${payload.userEmail}`);

// 새로운 토큰 저장
await this.redisService.set(
`access:${payload.userEmail}`,
newAccessToken,
60 * 60,
); // 1시간
await this.redisService.set(
`refresh:${payload.userEmail}`,
newRefreshToken,
7 * 24 * 60 * 60,
); // 7일

// 새 RefreshToken을 쿠키에 저장
res.cookie('refreshToken', newRefreshToken, {
httpOnly: true,
secure: true, // 개발 시 false
sameSite: 'none',
maxAge: 7 * 24 * 60 * 60 * 1000, // 7일
});

return {
accessToken: `Bearer ${newAccessToken}`,
};
Expand Down
138 changes: 0 additions & 138 deletions src/chat/chat.gateway.ts

This file was deleted.

9 changes: 0 additions & 9 deletions src/chat/chat.module.ts

This file was deleted.

84 changes: 0 additions & 84 deletions src/chat/chat.service.ts

This file was deleted.

Loading
Loading