Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
youngxdev committed Apr 6, 2024
1 parent e26d303 commit c135b13
Show file tree
Hide file tree
Showing 17 changed files with 299 additions and 265 deletions.
26 changes: 0 additions & 26 deletions src/auth/jwt/jwt.strategy.ts

This file was deleted.

29 changes: 29 additions & 0 deletions src/auth/strategy/jwt.strategy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// jwt.strategy.ts
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { UserService } from '../../modules/user/user.service';
import { UnauthorizedException } from '@nestjs/common';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(private readonly userService: UserService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: process.env.JWT_SECRET,
});
}

async validate(payload: any) {
const id = payload.id;
if (!id) {
throw new UnauthorizedException();
}
const user = await this.userService.getUserById(id);
if (!user) {
throw new UnauthorizedException();
}
return user;
}
}
87 changes: 46 additions & 41 deletions src/modules/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,58 +10,62 @@ import {
Res,
Req,
UseGuards,
} from "@nestjs/common";
import { ApiTags, ApiResponse, ApiOperation, ApiHeader } from "@nestjs/swagger";
import { CreateTokenRequestDto } from "./dto/create-token-request.dto";
import { CreateTokenResponseDto } from "./dto/create-token-response.dto";
import { RefreshTokenRequestDto } from "./dto/refresh-token-request.dto";
import { RefreshTokenResponseDto } from "./dto/refresh-token-response.dto";
import { AuthService } from "./auth.service";
import { Response } from "express";
import { KakaoAuthGuard } from "src/auth/guard/kakao.auth.guard";
import { SocialLoginRequestDto } from "./dto/social-login-request.dto";
import { GoogleAuthGuard } from "src/auth/guard/google.auth.guard";
import { CreateUserInfoResponseDto } from "../user/dto/create-user-info-response.dto";
} from '@nestjs/common';
import { ApiTags, ApiResponse, ApiOperation, ApiHeader } from '@nestjs/swagger';
import { CreateTokenRequestDto } from './dto/create-token-request.dto';
import { CreateTokenResponseDto } from './dto/create-token-response.dto';
import { RefreshTokenRequestDto } from './dto/refresh-token-request.dto';
import { RefreshTokenResponseDto } from './dto/refresh-token-response.dto';
import { AuthService } from './auth.service';
import { Response } from 'express';
import { KakaoAuthGuard } from 'src/auth/guard/kakao.auth.guard';
import { SocialLoginRequestDto } from './dto/social-login-request.dto';
import { GoogleAuthGuard } from 'src/auth/guard/google.auth.guard';
import { CreateUserInfoResponseDto } from '../user/dto/create-user-info-response.dto';

@ApiTags("auth")
@Controller({ path: "auth" })
@ApiTags('auth')
@Controller({ path: 'auth' })
export class AuthController {
constructor(private readonly authService: AuthService) {}

@Post("token")
@ApiOperation({ summary: "로그인", description: "토큰 발급" })
@Post('token')
@ApiOperation({ summary: '로그인', description: '토큰 발급' })
@ApiResponse({
status: 201,
description: "Created",
description: 'Created',
type: CreateTokenResponseDto,
})
@ApiResponse({ status: 400, description: "Bad request" })
@ApiResponse({ status: 400, description: 'Bad request' })
@HttpCode(HttpStatus.CREATED)
async createToken(
@Body() createTokenInfoDto: CreateTokenRequestDto,
@Res() res: Response,
) {
const tokens = await this.authService.create(createTokenInfoDto);

res.cookie("access_token", tokens.access_token, {
res.cookie('access_token', tokens.access_token, {
httpOnly: true,
expires: new Date(Date.now() + 15 * 60 * 1000), // 1h
});

res.cookie("refresh_token", tokens.refresh_token, {
res.cookie('refresh_token', tokens.refresh_token, {
httpOnly: true,
expires: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 30d
});
res.setHeader("access_token", tokens.access_token);
res.setHeader("refresh_token", tokens.refresh_token);
return res.status(HttpStatus.CREATED).send();
res.setHeader('access_token', tokens.access_token);
res.setHeader('refresh_token', tokens.refresh_token);

res.status(HttpStatus.CREATED).send();
}

@Post("token/refresh")
@ApiOperation({ summary: "토큰 재발급", description: "토큰 재발급" })
@Post('token/refresh')
@ApiOperation({
summary: '토큰 재발급',
description: '토큰 재발급',
})
@ApiResponse({
status: 201,
description: "Created",
description: 'Created',
type: RefreshTokenResponseDto,
})

Expand All @@ -73,54 +77,55 @@ export class AuthController {
) {
const tokens = await this.authService.refreshToken(refreshTokenInfoDto);

res.cookie("access_token", tokens.access_token, {
res.cookie('access_token', tokens.access_token, {
httpOnly: true,
expires: new Date(Date.now() + 15 * 60 * 1000), // 1h
});

res.cookie("refresh_token", tokens.refresh_token, {
res.cookie('refresh_token', tokens.refresh_token, {
httpOnly: true,
expires: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 30d
});
res.setHeader("access_token", tokens.access_token);
res.setHeader("refresh_token", tokens.refresh_token);
return res.status(HttpStatus.CREATED).send();
res.setHeader('access_token', tokens.access_token);
res.setHeader('refresh_token', tokens.refresh_token);

res.status(HttpStatus.CREATED).send();
}

@ApiOperation({
summary: "카카오 소셜로그인",
description: "기가입 유저는 로그인, 신규 유저는 회원가입 진행",
summary: '카카오 소셜로그인',
description: '기가입 유저는 로그인, 신규 유저는 회원가입 진행',
})
@ApiResponse({
status: 201,
description: "Created",
description: 'Created',
})
@UseGuards(KakaoAuthGuard)
@Get("login/kakao")
@Get('login/kakao')
async loginWithKakao(
@Req() req: Request,
@Res({ passthrough: true }) res: Response,
): Promise<CreateTokenResponseDto | CreateUserInfoResponseDto> {
const user = req["user"] as SocialLoginRequestDto;
const user = req['user'] as SocialLoginRequestDto;

return await this.authService.OAuthLogin(user);
}

@ApiOperation({
summary: "구글 소셜로그인",
description: "기가입 유저는 로그인, 신규 유저는 회원가입 진행",
summary: '구글 소셜로그인',
description: '기가입 유저는 로그인, 신규 유저는 회원가입 진행',
})
@ApiResponse({
status: 201,
description: "Created",
description: 'Created',
})
@UseGuards(GoogleAuthGuard)
@Get("login/google")
@Get('login/google')
async loginWithGoogle(
@Req() req: Request,
@Res({ passthrough: true }) res: Response,
): Promise<CreateTokenResponseDto | CreateUserInfoResponseDto> {
const user = req["user"] as SocialLoginRequestDto;
const user = req['user'] as SocialLoginRequestDto;

return await this.authService.OAuthLogin(user);
}
Expand Down
28 changes: 14 additions & 14 deletions src/modules/auth/auth.module.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { Module } from "@nestjs/common";
import { JwtModule } from "@nestjs/jwt";
import { AuthService } from "./auth.service";
import { AuthRepository } from "./auth.repository";
import { AuthController } from "./auth.controller";
import { DynamoDBModule } from "../../database/dynamodb/dynamodb.module";
import { JwtStrategy } from "../../auth/jwt/jwt.strategy";
import { PassportModule } from "@nestjs/passport";
import { UserModule } from "../user/user.module";
import { KakaoStrategy } from "src/auth/strategy/kakao.strategy";
import { UserService } from "../user/user.service";
import { UserRepository } from "../user/user.repository";
import { GoogleStrategy } from "src/auth/strategy/google.strategy";
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { AuthService } from './auth.service';
import { AuthRepository } from './auth.repository';
import { AuthController } from './auth.controller';
import { DynamoDBModule } from '../../database/dynamodb/dynamodb.module';
import { JwtStrategy } from '../../auth/strategy/jwt.strategy';
import { PassportModule } from '@nestjs/passport';
import { UserModule } from '../user/user.module';
import { KakaoStrategy } from 'src/auth/strategy/kakao.strategy';
import { UserService } from '../user/user.service';
import { UserRepository } from '../user/user.repository';
import { GoogleStrategy } from 'src/auth/strategy/google.strategy';

@Module({
imports: [
DynamoDBModule,
PassportModule,
JwtModule.register({
secret: process.env.JWT_SECRET,
signOptions: { expiresIn: "1h" },
signOptions: { expiresIn: '1h' },
}),
UserModule,
],
Expand Down
15 changes: 7 additions & 8 deletions src/modules/auth/auth.repository.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import { Injectable, Inject } from "@nestjs/common";
import { DynamoDBDocument } from "@aws-sdk/lib-dynamodb";
import { Injectable, Inject } from '@nestjs/common';
import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';

@Injectable()
export class AuthRepository {
private tableName: string;
constructor(@Inject("DYNAMODB") private dynamoDb: DynamoDBDocument) {
const env = process.env.NODE_ENV;
this.tableName = (env === "dev" ? "Dev_" : "") + "UserInfoTest";
constructor(@Inject('DYNAMODB') private dynamoDb: DynamoDBDocument) {
this.tableName = process.env.AWS_DYNAMODB_TABLE_NAME;
}

async findOneByEmail(email: string): Promise<any> {
const result = await this.dynamoDb.query({
TableName: this.tableName,
IndexName: "email-index",
KeyConditionExpression: "email = :email",
IndexName: 'email-index',
KeyConditionExpression: 'email = :email',
ExpressionAttributeValues: {
":email": email,
':email': email,
},
});

Expand Down
39 changes: 20 additions & 19 deletions src/modules/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Injectable } from "@nestjs/common";
import { UnauthorizedException } from "@nestjs/common";
import { CreateTokenRequestDto } from "./dto/create-token-request.dto";
import { RefreshTokenRequestDto } from "./dto/refresh-token-request.dto";
import { AuthRepository } from "./auth.repository";
import { JwtService } from "@nestjs/jwt";
import * as bcrypt from "bcrypt";
import { CreateTokenResponseDto } from "./dto/create-token-response.dto";
import { RefreshTokenResponseDto } from "./dto/refresh-token-response.dto";
import { SocialLoginRequestDto } from "./dto/social-login-request.dto";
import { UserService } from "../user/user.service";
import { CreateUserInfoResponseDto } from "../user/dto/create-user-info-response.dto";
import { Injectable } from '@nestjs/common';
import { UnauthorizedException } from '@nestjs/common';
import { CreateTokenRequestDto } from './dto/create-token-request.dto';
import { RefreshTokenRequestDto } from './dto/refresh-token-request.dto';
import { AuthRepository } from './auth.repository';
import { JwtService } from '@nestjs/jwt';
import * as bcrypt from 'bcrypt';
import { CreateTokenResponseDto } from './dto/create-token-response.dto';
import { RefreshTokenResponseDto } from './dto/refresh-token-response.dto';
import { SocialLoginRequestDto } from './dto/social-login-request.dto';
import { UserService } from '../user/user.service';
import { CreateUserInfoResponseDto } from '../user/dto/create-user-info-response.dto';

@Injectable()
export class AuthService {
Expand All @@ -32,19 +32,20 @@ export class AuthService {
userInfo: CreateTokenRequestDto,
): Promise<CreateTokenResponseDto> {
const user = await this.validateUser(userInfo.email, userInfo.password);

if (!user) {
throw new UnauthorizedException(
"User not found or password does not match",
'User not found or password does not match',
);
}

// JWT 토큰 생성
const payload = { Id: user.Id, SortKey: user.SortKey };
const payload = { id: user.PK };
return {
access_token: this.jwtService.sign({ ...payload, isRefreshToken: false }),
refresh_token: this.jwtService.sign(
{ ...payload, isRefreshToken: true },
{ expiresIn: "30d" },
{ expiresIn: '30d' },
),
};
}
Expand All @@ -59,19 +60,19 @@ export class AuthService {
payload = this.jwtService.verify(refreshToken);

if (!payload.isRefreshToken) {
throw new UnauthorizedException("Invalid token");
throw new UnauthorizedException('Invalid token');
}
} catch (error) {
throw new UnauthorizedException("Invalid token");
throw new UnauthorizedException('Invalid token');
}

// JWT 토큰 생성
payload = { Id: payload.Id, SortKey: payload.SortKey };
payload = { id: payload.id };
return {
access_token: this.jwtService.sign({ ...payload, isRefreshToken: false }),
refresh_token: this.jwtService.sign(
{ ...payload, isRefreshToken: true },
{ expiresIn: "30d" },
{ expiresIn: '30d' },
),
};
}
Expand Down
Loading

0 comments on commit c135b13

Please sign in to comment.