-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Feat: #80 로그인 기능 초안 작성 * Test: #80 로그인 모킹 함수 작성 * Feat: #80 로그인 관리 저장소 로직 일부 수정 * Feat: #80 로그인 로직, 모킹 함수 일부 수정 및 요청 인터셉트 추가 * Feat: #80 axiosProvider에 응답 인터셉터 추가 * Feat: #80 access token 저장 위치 변경 - 기존 cookie에서 zustand store로 저장 위치 변경 * Chore: #80 불필요한 패키지 제거, 설치 및 유저아이디 변수명 변경 * Feat: #80 refresh token 갱신 모킹 함수 작성 * Feat: #80 refresh token 만료 시 에러 처리 구현 * Feat: #80 프로필 이미지 URL 해제 코드 적용 * Feat: #80 인터셉터 로직 일부 수정 및 로그인 API 호출 로직에 useMutation 훅 적용 * Feat: #80 모킹 함수에 토큰 발급 시간 관련 로직 추가 * Feat: #80 zustand authStore에서 persist 미들웨어 제거 * Feat: #80 로그인 코드 로직을 전체적으로 수정 * Refactor: #80 URL revoke를 위한 로직 변경 및 파일 경로 수정, 시간 상수 활용 코드 변경 * Feat: #80 로그인 API의 withCredentials 옵션 삭제, 토큰 발급 실패 시 에러 처리 방식 변경 * Feat: #80 로그인 API 호출 방식 변경 * Feat: #80 authStore에 AT 만료 시간 추가 * Feat: #80 authStore AT 자동 만료 기능 추가 * Fix: #80 Invalid hook call 에러 해결 * Formatting: #80 import 경로 정리 * Feat: #80 핸들러 타입 처리 및 이미지 컨테이너의 불필요한 revoke 코드 삭제 * Feat: #80 로그인 API 호출 시 useAxios 훅 적용
- Loading branch information
Showing
15 changed files
with
323 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,7 +25,7 @@ export const JWT_TOKEN_DUMMY = 'mocked-header.mocked-payload-4.mocked-signature' | |
export const USER_INFO_DUMMY = { | ||
provider: 'LOCAL', | ||
userId: 1, | ||
id: 'test123', | ||
username: 'test123', | ||
email: '[email protected]', | ||
nickname: 'momoco', | ||
profileUrl: '', | ||
|
@@ -37,7 +37,7 @@ export const USER_INFO_DUMMY = { | |
export const USER_DUMMY: User[] = [ | ||
{ | ||
userId: 1, | ||
id: null, | ||
username: null, | ||
email: '[email protected]', | ||
provider: 'GOOGLE', | ||
nickname: '판다', | ||
|
@@ -47,7 +47,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 2, | ||
id: null, | ||
username: null, | ||
email: '[email protected]', | ||
provider: 'KAKAO', | ||
nickname: '카멜레온', | ||
|
@@ -57,7 +57,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 3, | ||
id: null, | ||
username: null, | ||
email: '[email protected]', | ||
provider: 'GOOGLE', | ||
nickname: '랫서판다', | ||
|
@@ -67,7 +67,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 4, | ||
id: null, | ||
username: null, | ||
email: '[email protected]', | ||
provider: 'KAKAO', | ||
nickname: '북금곰', | ||
|
@@ -77,7 +77,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 5, | ||
id: null, | ||
username: null, | ||
email: '[email protected]', | ||
provider: 'KAKAO', | ||
nickname: '호랑이', | ||
|
@@ -87,7 +87,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 6, | ||
id: null, | ||
username: null, | ||
email: '[email protected]', | ||
provider: 'GOOGLE', | ||
nickname: '나무늘보', | ||
|
@@ -97,7 +97,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 7, | ||
id: null, | ||
username: null, | ||
email: '[email protected]', | ||
provider: 'KAKAO', | ||
nickname: '웜뱃', | ||
|
@@ -107,7 +107,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 8, | ||
id: null, | ||
username: null, | ||
email: '[email protected]', | ||
provider: 'GOOGLE', | ||
nickname: '벨루가', | ||
|
@@ -117,7 +117,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 9, | ||
id: null, | ||
username: null, | ||
email: '[email protected]', | ||
provider: 'KAKAO', | ||
nickname: '펭귄', | ||
|
@@ -127,7 +127,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 10, | ||
id: null, | ||
username: null, | ||
email: '[email protected]', | ||
provider: 'GOOGLE', | ||
nickname: '비버', | ||
|
@@ -137,7 +137,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 11, | ||
id: 'eleven', | ||
username: 'eleven', | ||
email: '[email protected]', | ||
provider: 'LOCAL', | ||
nickname: '판다아빠', | ||
|
@@ -147,7 +147,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 12, | ||
id: 'twelve', | ||
username: 'twelve', | ||
email: '[email protected]', | ||
provider: 'LOCAL', | ||
nickname: '판다엄마', | ||
|
@@ -157,7 +157,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 13, | ||
id: 'thirteen', | ||
username: 'thirteen', | ||
email: '[email protected]', | ||
provider: 'LOCAL', | ||
nickname: '판다형', | ||
|
@@ -167,7 +167,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 14, | ||
id: 'fourteen', | ||
username: 'fourteen', | ||
email: '[email protected]', | ||
provider: 'LOCAL', | ||
nickname: '판다누나', | ||
|
@@ -177,7 +177,7 @@ export const USER_DUMMY: User[] = [ | |
}, | ||
{ | ||
userId: 15, | ||
id: 'fifteen', | ||
username: 'fifteen', | ||
email: '[email protected]', | ||
provider: 'LOCAL', | ||
nickname: '판다동생', | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import { http, HttpResponse } from 'msw'; | ||
import { AUTH_SETTINGS } from '@constants/settings'; | ||
import { UserSignInForm } from '@/types/UserType'; | ||
|
||
const BASE_URL = import.meta.env.VITE_BASE_URL; | ||
|
||
// TODO: 타입 분리하기 | ||
type Tokens = { | ||
accessToken: string; | ||
accessTokenExpiresAt: number; | ||
refreshToken: string; | ||
refreshTokenExpiresAt: number; | ||
}; | ||
|
||
// TODO: 토큰 관리 변수 분리 | ||
let tokens: Tokens | null = null; | ||
|
||
const accessTokenExpiryDate = new Date(Date.now() + AUTH_SETTINGS.ACCESS_TOKEN_EXPIRATION).toISOString(); | ||
const refreshTokenExpiryDate = new Date(Date.now() + AUTH_SETTINGS.REFRESH_TOKEN_EXPIRATION).toISOString(); | ||
|
||
const authServiceHandler = [ | ||
// 로그인 API | ||
http.post(`${BASE_URL}/user/login`, async ({ request }) => { | ||
const { username, password } = (await request.json()) as UserSignInForm; | ||
|
||
if (username === 'test' && password === 'test@123') { | ||
const accessToken = 'mockedAccessToken'; | ||
const refreshToken = 'mockedRefreshToken'; | ||
const currentTime = Date.now(); | ||
|
||
// 토큰 및 발급 시간 저장 | ||
tokens = { | ||
accessToken, | ||
accessTokenExpiresAt: currentTime + AUTH_SETTINGS.ACCESS_TOKEN_EXPIRATION, | ||
refreshToken, | ||
refreshTokenExpiresAt: currentTime + AUTH_SETTINGS.REFRESH_TOKEN_EXPIRATION, | ||
}; | ||
|
||
return new HttpResponse(null, { | ||
status: 200, | ||
headers: { | ||
Authorization: `Bearer ${accessToken}`, | ||
'Set-Cookie': `refreshToken=${refreshToken}; HttpOnly; SameSite=Strict; Secure; Path=/; Expires=${refreshTokenExpiryDate}; Max-Age=${AUTH_SETTINGS.REFRESH_TOKEN_EXPIRATION / 1000}`, | ||
}, | ||
}); | ||
} | ||
return HttpResponse.json({ message: '아이디 또는 비밀번호가 잘못되었습니다.' }, { status: 401 }); | ||
}), | ||
|
||
// TODO: 액세스 토큰 발급 방식이 확정지어지면 수정하기 | ||
// 액세스 토큰 갱신 API | ||
http.post(`${BASE_URL}/user/login/refresh`, async ({ cookies }) => { | ||
const { refreshToken } = cookies; | ||
|
||
// TODO: 토큰 관리 변수 분리 | ||
if (tokens === null) { | ||
return HttpResponse.json({ message: '로그인 세션이 존재하지 않습니다.' }, { status: 401 }); | ||
} | ||
|
||
// 리프레시 토큰 검증 | ||
if (refreshToken === tokens.refreshToken) { | ||
const currentTime = Date.now(); | ||
|
||
// 리프레시 토큰 만료 체크 | ||
if (currentTime >= tokens.refreshTokenExpiresAt) { | ||
tokens = null; | ||
return HttpResponse.json({ message: '리프레시 토큰이 만료되었습니다.' }, { status: 401 }); | ||
} | ||
|
||
// 액세스 토큰 갱신 | ||
const newAccessToken = 'newMockedAccessToken'; | ||
tokens.accessToken = newAccessToken; | ||
tokens.accessTokenExpiresAt = currentTime + AUTH_SETTINGS.ACCESS_TOKEN_EXPIRATION; | ||
|
||
return new HttpResponse(null, { | ||
status: 200, | ||
headers: { | ||
Authorization: `Bearer ${newAccessToken}`, | ||
'Set-Cookie': `refreshToken=${refreshToken}; HttpOnly; SameSite=Strict; Secure; Path=/; Expires=${refreshTokenExpiryDate}; Max-Age=${AUTH_SETTINGS.REFRESH_TOKEN_EXPIRATION / 1000}`, | ||
}, | ||
}); | ||
} | ||
return HttpResponse.json({ message: '리프레시 토큰이 유효하지 않습니다.' }, { status: 401 }); | ||
}), | ||
]; | ||
|
||
export default authServiceHandler; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.