Skip to content

Commit

Permalink
Merge pull request #48 from jihwooon/issue-35
Browse files Browse the repository at this point in the history
JWT Token 발급을 리팩터링 하라
  • Loading branch information
jihwooon authored Sep 14, 2023
2 parents 073e6ea + 3d752e1 commit c2ff63c
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 29 deletions.
12 changes: 6 additions & 6 deletions server/src/auth/signin/application/signin.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ export class SigninService {
throw new BadRequestException('패스워드가 일치 하지 않습니다')
}

const accessTokenExpireTime = this.jwtProvider.createAccessTokenExpireTime()
const refreshTokenExpireTime = this.jwtProvider.createRefreshTokenExpireTime()
const generateAccessToken = this.jwtProvider.generateAccessToken(member.memberId)
const generateRefreshToken = this.jwtProvider.generateRefreshToken(member.memberId)

return {
accessToken: this.jwtProvider.generateAccessToken(member.memberId, accessTokenExpireTime),
refreshToken: this.jwtProvider.generateRefreshToken(member.memberId, refreshTokenExpireTime),
accessTokenExpireTime: accessTokenExpireTime,
refreshTokenExpireTime: refreshTokenExpireTime,
accessToken: generateAccessToken.accessToken,
accessTokenExpireTime: generateAccessToken.accessTokenExpireTime,
refreshToken: generateRefreshToken.refreshToken,
refreshTokenExpireTime: generateRefreshToken.refreshTokenExpireTime,
}
}
}
12 changes: 6 additions & 6 deletions server/src/auth/signup/application/signup.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ export class SignupService {
new Member({ email: email, password: hashedPassword, memberName: memberName }),
)

const accessTokenExpireTime = this.jwtProvider.createAccessTokenExpireTime()
const refreshTokenExpireTime = this.jwtProvider.createRefreshTokenExpireTime()
const generateAccessToken = this.jwtProvider.generateAccessToken(id)
const generateRefreshToken = this.jwtProvider.generateRefreshToken(id)

return {
accessToken: this.jwtProvider.generateAccessToken(id, accessTokenExpireTime),
refreshToken: this.jwtProvider.generateRefreshToken(id, refreshTokenExpireTime),
accessTokenExpireTime: accessTokenExpireTime,
refreshTokenExpireTime: refreshTokenExpireTime,
accessToken: generateAccessToken.accessToken,
accessTokenExpireTime: generateAccessToken.accessTokenExpireTime,
refreshToken: generateRefreshToken.refreshToken,
refreshTokenExpireTime: generateRefreshToken.refreshTokenExpireTime,
}
}
}
39 changes: 31 additions & 8 deletions server/src/jwt/jwt.provider.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Test, TestingModule } from '@nestjs/testing'
import { JwtProvider } from './jwt.provider'
import { BadRequestException, UnauthorizedException } from '@nestjs/common'
import { TokenType } from './token-type.enum'

describe('JwtProvider class', () => {
let jwtProvider: JwtProvider

let INVALID_ACCESS_TOKEN =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjp7Im1lbWJlcklkIjoxLCJlbWFpbCI6ImFiY0BlbWFpbC5jb20iLCJtZW1iZXJOYW1lIjoi7ZmN6ri464-ZIiwibWVtYmVyVHlwZSI6IkdFTkVSQUwiLCJwYXNzd29yZCI6IjEyMzQ1Njc4IiwicmVmcmVzaFRva2VuIjoiZXlKaGJHY2lPaUpJIiwidG9rZW5FeHBpcmF0aW9uVGltZSI6IjIwMjMtMDktMDFUMjM6MTA6MDAuMDA5WiIsInJvbGUiOiJVU0VSIiwiY3JlYXRlVGltZSI6IjIwMjMtMDktMDFUMjM6MTA6MDAuMDA5WiIsInVwZGF0ZVRpbWUiOiIyMDIzLTA5LTAxVDIzOjEwOjAwLjAwOVoiLCJjcmVhdGVCeSI6Iu2Zjeq4uOuPmSIsIm1vZGlmaWVkQnkiOiLquYDssqDsiJgifSwiaWF0IjoxNjk0MzEzOTIyLCJleHAiOjE2OTQ0MDAzMjJ9.F5gN5mkLFk6nET2pJ78_sTdb_YIStT7u8ei7rfK1I123'
const Id = 1
const ID = 1
const ACCESS_TOKEN_EXPIRE = new Date(Date.now() + 86400000)
const REFRESH_TOKEN_EXPIRE = new Date(Date.now() + 1210500000)

Expand All @@ -22,7 +23,7 @@ describe('JwtProvider class', () => {
describe('generateAccessToken method', () => {
context('사용자 정보가 주어 질 때', () => {
it('accessToken을 리턴 해야 한다', () => {
const accessToken = jwtProvider.generateAccessToken(Id, ACCESS_TOKEN_EXPIRE)
const accessToken = jwtProvider.generateAccessToken(ID)

expect(accessToken).not.toEqual(
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjp7Im1lbWJlcklkIjoxLCJlbWFpbCI6ImFiY0BlbWFpbC5jb20iLCJtZW1iZXJOYW1lIjoi7ZmN6ri464-ZIiwibWVtYmVyVHlwZSI6IkdFTkVSQUwiLCJwYXNzd29yZCI6IjEyMzQ1Njc4IiwicmVmcmVzaFRva2VuIjoiZXlKaGJHY2lPaUpJIiwidG9rZW5FeHBpcmF0aW9uVGltZSI6IjIwMjMtMDktMDFUMjM6MTA6MDAuMDA5WiIsInJvbGUiOiJVU0VSIiwiY3JlYXRlVGltZSI6IjIwMjMtMDktMDFUMjM6MTA6MDAuMDA5WiIsInVwZGF0ZVRpbWUiOiIyMDIzLTA5LTAxVDIzOjEwOjAwLjAwOVoiLCJjcmVhdGVCeSI6Iu2Zjeq4uOuPmSIsIm1vZGlmaWVkQnkiOiLquYDssqDsiJgifSwiaWF0IjoxNjk0MzEzOTIyLCJleHAiOjE2OTQ0MDAzMjJ9.F5gN5mkLFk6nET2pJ78_sTdb_YIStT7u8ei7rfK1I7c',
Expand All @@ -32,7 +33,7 @@ describe('JwtProvider class', () => {
context('id가 null이 주어지면', () => {
it('BadRequestException를 던져야 한다', () => {
try {
jwtProvider.generateAccessToken(null, ACCESS_TOKEN_EXPIRE)
jwtProvider.generateAccessToken(null)
} catch (e) {
expect(e).toBeInstanceOf(BadRequestException)
expect(e.message).toEqual('id는 null이 될 수 없습니다')
Expand All @@ -42,7 +43,7 @@ describe('JwtProvider class', () => {
context('id가 undefined이 주어지면', () => {
it('BadRequestException를 던져야 한다', () => {
try {
jwtProvider.generateAccessToken(undefined, ACCESS_TOKEN_EXPIRE)
jwtProvider.generateAccessToken(undefined)
} catch (e) {
expect(e).toBeInstanceOf(BadRequestException)
expect(e.message).toEqual('id는 undefined이 될 수 없습니다')
Expand All @@ -54,7 +55,7 @@ describe('JwtProvider class', () => {
describe('generateRefreshToken method', () => {
context('사용자 정보가 주어 질 때', () => {
it('refreshToken을 리턴 해야 한다', () => {
const refreshToken = jwtProvider.generateRefreshToken(Id, REFRESH_TOKEN_EXPIRE)
const refreshToken = jwtProvider.generateRefreshToken(ID)

expect(refreshToken).not.toEqual(
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjp7Im1lbWJlcklkIjoxLCJlbWFpbCI6ImFiY0BlbWFpbC5jb20iLCJtZW1iZXJOYW1lIjoi7ZmN6ri464-ZIiwibWVtYmVyVHlwZSI6IkdFTkVSQUwiLCJwYXNzd29yZCI6IjEyMzQ1Njc4IiwicmVmcmVzaFRva2VuIjoiZXlKaGJHY2lPaUpJIiwidG9rZW5FeHBpcmF0aW9uVGltZSI6IjIwMjMtMDktMDFUMjM6MTA6MDAuMDA5WiIsInJvbGUiOiJVU0VSIiwiY3JlYXRlVGltZSI6IjIwMjMtMDktMDFUMjM6MTA6MDAuMDA5WiIsInVwZGF0ZVRpbWUiOiIyMDIzLTA5LTAxVDIzOjEwOjAwLjAwOVoiLCJjcmVhdGVCeSI6Iu2Zjeq4uOuPmSIsIm1vZGlmaWVkQnkiOiLquYDssqDsiJgifSwiaWF0IjoxNjk0MzEzOTIyLCJleHAiOjE2OTQ0MDAzMjJ9.F5gN5mkLFk6nET2pJ78_sTdb_YIStT7u8ei7rfK1I7c',
Expand All @@ -64,7 +65,7 @@ describe('JwtProvider class', () => {
context('id가 null이 주어지면', () => {
it('BadRequestException를 던져야 한다', () => {
try {
jwtProvider.generateRefreshToken(null, REFRESH_TOKEN_EXPIRE)
jwtProvider.generateRefreshToken(null)
} catch (e) {
expect(e).toBeInstanceOf(BadRequestException)
expect(e.message).toEqual('id는 null이 될 수 없습니다')
Expand All @@ -74,7 +75,7 @@ describe('JwtProvider class', () => {
context('id가 undefined이 주어지면', () => {
it('BadRequestException를 던져야 한다', () => {
try {
jwtProvider.generateRefreshToken(undefined, REFRESH_TOKEN_EXPIRE)
jwtProvider.generateRefreshToken(undefined)
} catch (e) {
expect(e).toBeInstanceOf(BadRequestException)
expect(e.message).toEqual('id는 undefined이 될 수 없습니다')
Expand All @@ -86,7 +87,8 @@ describe('JwtProvider class', () => {
describe('validateToken method', () => {
context('accessToken이 검증을 성공하면', () => {
it('id를 리턴 해야 한다.', () => {
const payload = jwtProvider.validateToken(jwtProvider.generateAccessToken(Id, ACCESS_TOKEN_EXPIRE))
const generateAccessToken = jwtProvider.generateAccessToken(ID)
const payload = jwtProvider.validateToken(generateAccessToken.accessToken)

expect(payload).toEqual(1)
})
Expand Down Expand Up @@ -152,4 +154,25 @@ describe('JwtProvider class', () => {
})
})
})

describe('generateToken method', () => {
context('id와 accessToken 만료 시간, Access Type이 주어지면', () => {
it('AccessToken을 리턴해야 한다', () => {
const accessToken = jwtProvider.generateToken(ID, ACCESS_TOKEN_EXPIRE, TokenType.ACCESS)

expect(accessToken).not.toEqual(
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjoxLCJpYXQiOjE2OTQ2NjY2MTksImV4cCI6MTY5NDY2NzI5Mywic3ViIjoiQUNDRVNTIn0.yrr0muDm32ddItUb3HAAR_bDapXp3t-tKFApU2Wowh8',
)
})
})
context('id와 refreshToken 만료 시간, Refresh Type이 주어지면', () => {
it('RefreshToken을 리턴해야 한다', () => {
const refreshToken = jwtProvider.generateToken(ID, REFRESH_TOKEN_EXPIRE, TokenType.REFRESH)

expect(refreshToken).not.toEqual(
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjoxLCJpYXQiOjE2OTQ2NjY2NDUsImV4cCI6MTY5NDY2NzQwNywic3ViIjoiUkVGUkVTSCJ9.twLp5ynQZaiAUF9DHNk9Z2xh-GaDeF5QAxk4JA2qW1I',
)
})
})
})
})
28 changes: 19 additions & 9 deletions server/src/jwt/jwt.provider.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,39 @@
import { Injectable, BadRequestException, UnauthorizedException } from '@nestjs/common'
import * as jwt from 'jsonwebtoken'
import * as dotenv from 'dotenv'
import { TokenType } from './token-type.enum'

dotenv.config()

@Injectable()
export class JwtProvider {
generateAccessToken(id: number, expireTime: Date) {
if (id == undefined || id == null) {
throw new BadRequestException(`id는 ${id}이 될 수 없습니다`)
generateAccessToken(id: number) {
const accessTokenExpireTime = this.createAccessTokenExpireTime()
const accessToken = this.generateToken(id, accessTokenExpireTime, TokenType.ACCESS)

return {
accessToken: accessToken,
accessTokenExpireTime: accessTokenExpireTime,
}
}

return jwt.sign({ payload: id }, process.env.JWT_SECRET, {
subject: 'ACCESS',
expiresIn: expireTime.getMilliseconds(),
})
generateRefreshToken(id: number) {
const refreshTokenExpireTime = this.createRefreshTokenExpireTime()
const refreshToken = this.generateToken(id, refreshTokenExpireTime, TokenType.REFRESH)

return {
refreshToken: refreshToken,
refreshTokenExpireTime: refreshTokenExpireTime,
}
}

generateRefreshToken(id: number, expireTime: Date) {
generateToken(id: number, expireTime: Date, tokenType: string) {
if (id == undefined || id == null) {
throw new BadRequestException(`id는 ${id}이 될 수 없습니다`)
}

return jwt.sign({ payload: id }, process.env.JWT_SECRET, {
subject: 'REFRESH',
subject: tokenType,
expiresIn: expireTime.getMilliseconds(),
})
}
Expand Down
4 changes: 4 additions & 0 deletions server/src/jwt/token-type.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum TokenType {
ACCESS = 'ACCESS',
REFRESH = 'REFRESH',
}

0 comments on commit c2ff63c

Please sign in to comment.