로그아웃 기능 추가
This commit is contained in:
@@ -55,11 +55,28 @@ export const register = async (data: RegisterData): Promise<{ message: string }>
|
||||
|
||||
// 로그아웃 API
|
||||
export const logout = async (): Promise<void> => {
|
||||
await axios.post('/auth/logout');
|
||||
try {
|
||||
// HttpOnly 쿠키 삭제를 위해 서버의 로그아웃 API를 GET 방식으로 호출
|
||||
await axios.get('/auth/logout');
|
||||
} catch (error) {
|
||||
// 서버 로그아웃 실패하더라도 클라이언트는 정리 진행
|
||||
}
|
||||
|
||||
// 로컬 스토리지 정리
|
||||
localStorage.removeItem('accessToken');
|
||||
localStorage.removeItem('refreshToken');
|
||||
document.cookie = 'access_token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/';
|
||||
document.cookie = 'refresh_token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/';
|
||||
|
||||
// 쿠키 정리
|
||||
const cookieNames = ['access_token', 'refresh_token'];
|
||||
const domain = window.location.hostname;
|
||||
const paths = ['/', '/api']; // 가능한 경로들
|
||||
|
||||
cookieNames.forEach(name => {
|
||||
paths.forEach(path => {
|
||||
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path}`;
|
||||
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path}; domain=${domain}`;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// 토큰이 유효한지 확인
|
||||
|
||||
@@ -19,12 +19,16 @@ import {
|
||||
cilSettings,
|
||||
cilTask,
|
||||
cilUser,
|
||||
cilAccountLogout,
|
||||
} from '@coreui/icons'
|
||||
import { useAuth } from 'src/hooks/useAuth'
|
||||
import CIcon from '@coreui/icons-react'
|
||||
|
||||
import avatar8 from 'src/assets/images/avatars/8.jpg'
|
||||
|
||||
const AppHeaderDropdown = () => {
|
||||
const { logout } = useAuth()
|
||||
|
||||
return (
|
||||
<CDropdown variant="nav-item">
|
||||
<CDropdownToggle className="py-0 pe-0" caret={false}>
|
||||
@@ -84,9 +88,9 @@ const AppHeaderDropdown = () => {
|
||||
</CBadge>
|
||||
</CDropdownItem>
|
||||
<CDropdownDivider />
|
||||
<CDropdownItem href="#">
|
||||
<CIcon icon={cilLockLocked} className="me-2" />
|
||||
Lock Account
|
||||
<CDropdownItem onClick={logout} style={{ cursor: 'pointer' }}>
|
||||
<CIcon icon={cilAccountLogout} className="me-2" />
|
||||
Logout
|
||||
</CDropdownItem>
|
||||
</CDropdownMenu>
|
||||
</CDropdown>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { createContext, useReducer, useEffect } from 'react';
|
||||
|
||||
import { isTokenValid, getAccessTokenFromCookie, getUserFromToken, getRefreshTokenFromCookie, renewAccessToken } from 'src/axios/authService';
|
||||
import { isTokenValid, getAccessTokenFromCookie, getUserFromToken, getRefreshTokenFromCookie, renewAccessToken, logout as apiLogout } from 'src/axios/authService';
|
||||
|
||||
// 사용자 타입 정의
|
||||
export interface Member {
|
||||
@@ -63,6 +63,9 @@ const authReducer = (state: AuthState, action: AuthAction): AuthState => {
|
||||
};
|
||||
case 'LOGOUT':
|
||||
localStorage.removeItem('accessToken');
|
||||
localStorage.removeItem('access_token');
|
||||
localStorage.removeItem('refreshToken');
|
||||
localStorage.removeItem('refresh_token');
|
||||
return {
|
||||
...state,
|
||||
isAuthenticated: false,
|
||||
@@ -72,6 +75,9 @@ const authReducer = (state: AuthState, action: AuthAction): AuthState => {
|
||||
};
|
||||
case 'AUTH_ERROR':
|
||||
localStorage.removeItem('accessToken');
|
||||
localStorage.removeItem('access_token');
|
||||
localStorage.removeItem('refreshToken');
|
||||
localStorage.removeItem('refresh_token');
|
||||
return {
|
||||
...state,
|
||||
isAuthenticated: false,
|
||||
@@ -114,8 +120,14 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
|
||||
};
|
||||
|
||||
// 로그아웃 함수
|
||||
const logout = () => {
|
||||
dispatch({ type: 'LOGOUT' });
|
||||
const logout = async () => {
|
||||
try {
|
||||
await apiLogout();
|
||||
} catch (error) {
|
||||
console.error('Logout failed:', error);
|
||||
} finally {
|
||||
dispatch({ type: 'LOGOUT' });
|
||||
}
|
||||
};
|
||||
|
||||
// 초기 인증 상태 확인
|
||||
|
||||
Reference in New Issue
Block a user