From 000c5d24c95f8eaa263575e2c1393041e8dc6068 Mon Sep 17 00:00:00 2001 From: ChoiGeon Date: Thu, 8 Aug 2024 12:53:00 +0900 Subject: [PATCH] =?UTF-8?q?=ED=86=A0=ED=81=B0=20=EC=9E=AC=EB=B0=9C?= =?UTF-8?q?=EA=B8=89=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/response.status.js | 3 + .../refreshToken/refreshToken.controller.js | 25 ++++++ .../refreshToken/refreshToken.service.js | 24 ++++++ src/index.js | 2 + src/routes/refreshToken.js | 6 ++ src/swagger/refreshToken.swagger.yaml | 77 +++++++++++++++++++ 6 files changed, 137 insertions(+) create mode 100644 src/domains/refreshToken/refreshToken.controller.js create mode 100644 src/domains/refreshToken/refreshToken.service.js create mode 100644 src/routes/refreshToken.js create mode 100644 src/swagger/refreshToken.swagger.yaml diff --git a/src/config/response.status.js b/src/config/response.status.js index eab5426..023110b 100644 --- a/src/config/response.status.js +++ b/src/config/response.status.js @@ -28,4 +28,7 @@ export const status = { TOKEN_EXPIRED: { status: StatusCodes.UNAUTHORIZED, isSuccess: false, code: "403", message: "토큰을 재발급 받아주세요." }, INVALID_TOKEN: { status: StatusCodes.UNAUTHORIZED, isSuccess: false, code: "403", message: "유효하지 않은 토큰입니다." }, + // refreshToken err + REFRESH_TOKEN_NOT_PROVIDED: { status: StatusCodes.UNAUTHORIZED, isSuccess: false, code: "401", message: "refresh 토큰이 제공되지 않았습니다." }, + REFRESH_TOKEN_INVALID: { status: StatusCodes.UNAUTHORIZED, isSuccess: false, code: "402", message: "유효하지 않은 refresh 토큰입니다." }, }; \ No newline at end of file diff --git a/src/domains/refreshToken/refreshToken.controller.js b/src/domains/refreshToken/refreshToken.controller.js new file mode 100644 index 0000000..3938fda --- /dev/null +++ b/src/domains/refreshToken/refreshToken.controller.js @@ -0,0 +1,25 @@ +import { response } from "../../config/response.js"; +import { status } from "../../config/response.status.js"; +import { refreshTokenService } from "./refreshToken.service.js"; + +export async function refreshTokenLogic(req, res) { + try { + const token = req.cookies.refreshToken; + if (!token) { + return res.send(response(status.REFRESH_TOKEN_NOT_PROVIDED)); + } + const result = await refreshTokenService(token); + + if (!result.success) { + return res.send(response(status.REFRESH_TOKEN_INVALID)); + } + + res.cookie('accessToken', result.accessToken, { httpOnly: true, secure: false }); + res.cookie('refreshToken', result.refreshToken, { httpOnly: true, secure: false }); + + return res.send(response(status.SUCCESS)); + } catch (err) { + console.error(err); + return res.send(response(status.INTERNAL_SERVER_ERROR)); + } +} diff --git a/src/domains/refreshToken/refreshToken.service.js b/src/domains/refreshToken/refreshToken.service.js new file mode 100644 index 0000000..f9d53dc --- /dev/null +++ b/src/domains/refreshToken/refreshToken.service.js @@ -0,0 +1,24 @@ +import jwt from 'jsonwebtoken'; + +export async function refreshTokenService(token) { + try { + const decoded = jwt.verify(token,process.env.JWT_SECRET_KEY); + + const accessToken = jwt.sign({ + uuid: decoded.uuid, + }, process.env.JWT_SECRET_KEY, { + expiresIn: '5m' + }); + + const refreshToken = jwt.sign({ + uuid: decoded.uuid, + }, process.env.JWT_SECRET_KEY, { + expiresIn: '1h' + }); + + return { success: true, accessToken, refreshToken }; + } catch (err) { + console.error(err); + return { success: false, message: '토큰 인증 오류' }; + } +} diff --git a/src/index.js b/src/index.js index 260ed30..75d1003 100644 --- a/src/index.js +++ b/src/index.js @@ -10,6 +10,7 @@ import { loginRouter } from './routes/login.js'; import { status } from './config/response.status.js'; import { BaseError } from './config/error.js'; import { response } from './config/response.js'; +import { refreshTokenRouter } from './routes/refreshToken.js'; const app = express(); const port = 3000; @@ -26,6 +27,7 @@ app.use('/api-docs', SwaggerUi.serve, SwaggerUi.setup(specs)); app.use("/FITple/signup",signupRouter); app.use("/FITple/login",loginRouter); +app.use("/FITple/refreshToken",refreshTokenRouter); app.use((req, res, next) => { const err = new BaseError(status.NOT_FOUND); diff --git a/src/routes/refreshToken.js b/src/routes/refreshToken.js new file mode 100644 index 0000000..8526e26 --- /dev/null +++ b/src/routes/refreshToken.js @@ -0,0 +1,6 @@ +import express from 'express'; +import { refreshTokenLogic } from '../domains/refreshToken/refreshToken.controller.js'; + +export const refreshTokenRouter = express.Router(); + +refreshTokenRouter.get('/',refreshTokenLogic); \ No newline at end of file diff --git a/src/swagger/refreshToken.swagger.yaml b/src/swagger/refreshToken.swagger.yaml new file mode 100644 index 0000000..7866342 --- /dev/null +++ b/src/swagger/refreshToken.swagger.yaml @@ -0,0 +1,77 @@ +paths: + /FITple/refreshToken: + get: + tags: + - RefreshToken + summary: 토큰 재발급 + responses: + '200': + description: 토큰 재발급 성공! + schema: + type: object + properties: + isSuccess: + type: boolean + example: true + code: + type: number + example: 200 + message: + type: string + example: "success!" + '400': + description: 잘못된 요청 + schema: + type: object + properties: + isSuccess: + type: boolean + example: false + code: + type: string + example: 400 + message: + type: string + example: 잘못된 요청입니다 + '401': + description: refresh 토큰이 존재하지 않음 + schema: + type: object + properties: + isSuccess: + type: boolean + example: false + code: + type: string + example: 401 + message: + type: string + example: refresh 토큰이 존재하지 않았습니다. + '402': + description: 유효하지 않는 refresh 토큰 + schema: + type: object + properties: + isSuccess: + type: boolean + example: false + code: + type: string + example: 402 + message: + type: string + example: 유효하지 않은 refresh 토큰입니다. + '500': + description: 서버 에러 + schema: + type: object + properties: + isSuccess: + type: boolean + example: false + code: + type: string + example: 500 + message: + type: string + example: 서버 에러, 관리자에게 문의 바랍니다.