- 자동 로그인 로직 cookie 로 변경
This commit is contained in:
17
src/main.ts
17
src/main.ts
@@ -5,11 +5,23 @@ import {
|
||||
NestFastifyApplication
|
||||
} from '@nestjs/platform-fastify';
|
||||
import { AllExceptionsFilter } from './common/filters/all-exceptions.filter';
|
||||
import fastifyCookie from '@fastify/cookie';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
|
||||
async function bootstrap() {
|
||||
const isProd = process.env.NODE_ENV === 'prod';
|
||||
let httpsOptions = {};
|
||||
if (!isProd) {
|
||||
const certPath = path.join(__dirname, "..\\..", "certs");
|
||||
httpsOptions = {
|
||||
key: fs.readFileSync(path.join(certPath, 'localhost+2-key.pem')),
|
||||
cert: fs.readFileSync(path.join(certPath, 'localhost+2.pem'))
|
||||
};
|
||||
}
|
||||
const app = await NestFactory.create<NestFastifyApplication>(
|
||||
AppModule,
|
||||
new FastifyAdapter()
|
||||
new FastifyAdapter({ https: httpsOptions })
|
||||
);
|
||||
app.enableCors({
|
||||
origin: (origin, callback) => {
|
||||
@@ -30,6 +42,9 @@ async function bootstrap() {
|
||||
|
||||
app.enableShutdownHooks();
|
||||
app.useGlobalFilters(new AllExceptionsFilter());
|
||||
app.register(fastifyCookie, {
|
||||
secret: process.env.JWT_SECRET
|
||||
});
|
||||
await app.listen(process.env.PORT ?? 3000, '0.0.0.0', () => { process.env.NODE_ENV !== 'prod' && console.log(`servier is running on ${process.env.PORT}`) });
|
||||
|
||||
}
|
||||
|
||||
@@ -5,19 +5,22 @@ import { JwtService } from '@nestjs/jwt';
|
||||
export class AuthService {
|
||||
constructor(private readonly jwtService: JwtService) {}
|
||||
|
||||
generateTokens(payload: any) {
|
||||
const accessToken = this.jwtService.sign(payload, { expiresIn: '5s' });
|
||||
const refreshToken = this.jwtService.sign({id: payload.id}, { expiresIn: '7d' });
|
||||
generateTokens(id: string) {
|
||||
const accessToken = this.jwtService.sign({id: id}, { expiresIn: '5s' });
|
||||
const refreshToken = this.jwtService.sign({id: id}, { expiresIn: '7d' });
|
||||
|
||||
return { accessToken, refreshToken };
|
||||
}
|
||||
|
||||
refreshTokens(refreshToken: string) {
|
||||
refreshTokens(id: string) {
|
||||
try {
|
||||
const payload = this.jwtService.verify(refreshToken);
|
||||
return this.generateTokens(payload);
|
||||
return this.generateTokens(id);
|
||||
} catch (e) {
|
||||
throw new UnauthorizedException('Invalid Refresh Token');
|
||||
}
|
||||
}
|
||||
|
||||
validateToken(token: string) {
|
||||
return this.jwtService.verify(token);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,33 @@
|
||||
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { FastifyRequest } from 'fastify';
|
||||
import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||
|
||||
const extractJwtFromCookie = (req: FastifyRequest | any): string | null => {
|
||||
if (req.cookies && req.cookies['refresh_token']) {
|
||||
return req.cookies['refresh_token'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class JwtRefreshStrategy extends PassportStrategy(Strategy, 'refresh-token') {
|
||||
constructor(configService: ConfigService) {
|
||||
super({
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
jwtFromRequest: ExtractJwt.fromExtractors([extractJwtFromCookie]),
|
||||
secretOrKey: configService.get<string>('JWT_SECRET')!,
|
||||
passReqToCallback: true
|
||||
});
|
||||
}
|
||||
|
||||
async validate(payload: any) {
|
||||
const token = ExtractJwt.fromAuthHeaderAsBearerToken();
|
||||
|
||||
if (!token) throw new UnauthorizedException('Invalid Refresh Token');
|
||||
async validate(req: FastifyRequest, payload: any) {
|
||||
const refreshToken = req.cookies['refresh_token'];
|
||||
if (!refreshToken) throw new UnauthorizedException('Invalid Refresh Token');
|
||||
|
||||
return {
|
||||
id: payload.id,
|
||||
token
|
||||
refreshToken
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Body, Controller, Get, Headers, Post, Query, Req, UseGuards } from "@nestjs/common";
|
||||
import { Body, Controller, Get, Headers, Post, Query, Req, Res, UseGuards } from "@nestjs/common";
|
||||
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";
|
||||
import type { FastifyReply, FastifyRequest } from "fastify";
|
||||
import { AuthGuard } from "@nestjs/passport";
|
||||
import { JwtAccessAuthGuard } from "src/middleware/auth/guard/access-token.guard";
|
||||
|
||||
@UseGuards(JwtAccessAuthGuard)
|
||||
@Controller('account')
|
||||
@@ -65,18 +66,44 @@ export class AccountController {
|
||||
|
||||
@Public()
|
||||
@Post('login')
|
||||
async login(@Body() body: DTO.LoginRequest): Promise<DTO.LoginResponse> {
|
||||
console.log('a');
|
||||
async login(@Body() body: DTO.LoginRequest, @Res({ passthrough: true }) res: FastifyReply): Promise<DTO.LoginResponse> {
|
||||
const result = await this.accountService.login(body);
|
||||
return result;
|
||||
if (result.success) {
|
||||
res.setCookie('refresh_token', result.refreshToken!, {
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
secure: true,
|
||||
maxAge: 7 * 24 * 60 * 60 * 1000
|
||||
});
|
||||
}
|
||||
return {
|
||||
success: result.success,
|
||||
message: result.message,
|
||||
error: result.error,
|
||||
accessToken: result.accessToken
|
||||
};
|
||||
}
|
||||
|
||||
@Public()
|
||||
@UseGuards(JwtRefreshAuthGuard)
|
||||
@UseGuards(AuthGuard('refresh-token'))
|
||||
@Get('refresh-access-token')
|
||||
async refreshAccessToken(@Req() req): Promise<DTO.RefreshAccessTokenResponse> {
|
||||
const id = req.user.id;
|
||||
const newAccessToken = this.accountService.refreshAccessToken(id);
|
||||
return newAccessToken;
|
||||
async refreshAccessToken(@Req() req, @Res({ passthrough: true }) res: FastifyReply): Promise<DTO.RefreshAccessTokenResponse> {
|
||||
const result = await this.accountService.refreshAccessToken(req.user.id);
|
||||
if (result.success) {
|
||||
res.setCookie('refresh_token', result.refreshToken!, {
|
||||
httpOnly: true,
|
||||
path: '/',
|
||||
secure: true,
|
||||
maxAge: 7 * 24 * 60 * 60 * 1000
|
||||
});
|
||||
|
||||
return {
|
||||
success: result.success,
|
||||
message: result.message,
|
||||
error: result.error,
|
||||
accessToken: result.accessToken
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -95,13 +95,9 @@ export class AccountService {
|
||||
}
|
||||
|
||||
{
|
||||
const { id, accountId, status, isDeleted, birthday } = queryResult[0];
|
||||
const { id } = queryResult[0];
|
||||
|
||||
const payload = {
|
||||
id, accountId, status, isDeleted, birthday
|
||||
};
|
||||
|
||||
const { accessToken, refreshToken } = this.authService.generateTokens(payload);
|
||||
const { accessToken, refreshToken } = this.authService.generateTokens(id);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
|
||||
@@ -2,5 +2,5 @@ import { BaseResponseDto } from "../base-response.dto";
|
||||
|
||||
export class RefreshAccessTokenResponseDto extends BaseResponseDto{
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
refreshToken?: string;
|
||||
}
|
||||
Reference in New Issue
Block a user