From 1b39debe9c834ebbfb1c63be6d72c63e25d76b66 Mon Sep 17 00:00:00 2001 From: scarf Date: Mon, 14 Aug 2023 20:12:10 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=A1=9C=EA=B7=B8=EC=95=84=EC=9B=83?= =?UTF-8?q?=EC=8B=9C=20`access=5Ftoken`=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/config/index.ts | 17 +++++++++++++++++ backend/src/v1/auth/auth.controller.ts | 12 +++++++++--- backend/src/v1/auth/auth.jwt.ts | 11 ++--------- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index d3c56bd1..d8b5a3b3 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -8,6 +8,7 @@ import { getNaverBookApiOption } from './naverBookApiOption'; import { getOauth42ApiOption, getOauthUrlOption } from './oauthOption'; import { getRuntimeMode } from './runtimeOption'; import { getSlackbotOAuthToken } from './slackbotOAuthTokenOption'; +import type { CookieOptions } from 'express'; export * as logFormatOption from './logOption'; @@ -38,3 +39,19 @@ export const jwtOption = { /** JWT 인증 토큰 시드 */ secret: getJwtSecret(process.env), }; + +/** + * `path` 와 `domain`은 쿠키 설정시와 삭제시 같아야 합니다. + * + * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#third-party_cookies | MDN#Third-party cookies} + */ +export const cookieOptions = { + /** 브라우저에서만 쿠키를 사용할 수 있게 설정 */ + httpOnly: true, + path: '/', + domain: jwtOption.domain, + /** https 에서만 사용할 수 있도록 설정 */ + secure: jwtOption.secure, + /** 같은 도메인의에서만 쿠키를 사용할 수 있는 'strict' 값 설정 */ + sameSite: 'lax', +} satisfies CookieOptions; diff --git a/backend/src/v1/auth/auth.controller.ts b/backend/src/v1/auth/auth.controller.ts index e2a63eb2..52aadbea 100644 --- a/backend/src/v1/auth/auth.controller.ts +++ b/backend/src/v1/auth/auth.controller.ts @@ -2,7 +2,7 @@ import * as bcrypt from 'bcrypt'; import { NextFunction, Request, Response } from 'express'; import * as status from 'http-status'; import { randomUUID } from 'node:crypto'; -import { oauth42ApiOption, oauthUrlOption } from '~/config'; +import { cookieOptions, oauth42ApiOption, oauthUrlOption } from '~/config'; import { logger } from '~/logger'; import UsersService from '~/v1/users/users.service'; import * as errorCode from '~/v1/utils/error/errorCode'; @@ -121,9 +121,15 @@ export const login = async (req: Request, res: Response, next: NextFunction): Pr } }; +/** + * @remarks + * + * 쿠키를 설정했을때와 같은 옵션으로 쿠키를 삭제해야 합니다. + * + * @see {@link authJwt.saveJwt} + */ export const logout = (req: Request, res: Response) => { - res.cookie('access_token', null, { maxAge: 0, httpOnly: true }); - res.status(204).send(); + res.clearCookie('access_token', cookieOptions).status(204).send(); }; export const getIntraAuthentication = (req: Request, res: Response) => { diff --git a/backend/src/v1/auth/auth.jwt.ts b/backend/src/v1/auth/auth.jwt.ts index 7d7419c1..b9903ea3 100644 --- a/backend/src/v1/auth/auth.jwt.ts +++ b/backend/src/v1/auth/auth.jwt.ts @@ -1,6 +1,6 @@ import { Request, Response } from 'express'; import * as jwt from 'jsonwebtoken'; -import { jwtOption } from '~/config'; +import { cookieOptions, jwtOption } from '~/config'; import { User } from '../DTO/users.model'; /** @@ -26,19 +26,12 @@ export const issueJwt = (user: User) => { * * issueJwt 함수를 이용해 JWT를 생성하고, 토큰을 클라이언트 Cookie에 저장한다. * 설정값 설명 - * httpOnly : 브라우저에서만 쿠키를 사용할 수 있게 설정 - * secure : https 에서만 사용할 수 있도록 설정 - * sameSite : 같은 도메인의에서만 쿠키를 사용할 수 있는 'strict' 값 설정 * expires: 밀리세컨드 값으로 설정해야하고, 1000 * 60 * 480 = 8시간으로 설정 */ export const saveJwt = async (req: Request, res: Response, user: User) : Promise => { const token = issueJwt(user); res.cookie('access_token', token, { - httpOnly: true, - secure: jwtOption.secure, // ANCHOR https 연결시에는 true로 설정해주어야함. - sameSite: 'lax', - path: '/', - domain: jwtOption.domain, + ...cookieOptions, expires: new Date(new Date().getTime() + 1000 * 60 * 480), }); };