Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FE]리프레시 토큰을 이용한 로그인 유지 기능 Dev client#19/watch list #175

Open
wants to merge 1 commit into
base: dev-client
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 49 additions & 19 deletions client/src/hooks/customHooks/useAutoLogout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,30 @@ import { secondAlarmTime, lastAlarmTime } from '../../utils/setAutoLogoutAlarm';
const useAutoLogout = () => {
const dispatch = useDispatch();

// 리프레시 토큰을 사용하여 새 엑세스 토큰을 요청하는 함수
const requestNewAccessToken = async () => {
const refreshToken = localStorage.getItem("refreshToken");
try {
const response = await fetch('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/tokens/refresh', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ refreshToken: refreshToken })
});

if (response.status !== 201) {
throw new Error('Failed to fetch new access token');
}

const data = await response.json();
return data.accessToken;
} catch (error) {
console.error(error);
return null;
}
};

useEffect(() => {
const accessToken = localStorage.getItem('accessToken');
if (accessToken !== null) {
Expand All @@ -15,29 +39,35 @@ const useAutoLogout = () => {
const autoLogoutLastAlarm = localStorage.getItem('autoLogoutLastAlarm');

if (autoLogoutSecondAlarm !== null) {
if (currentTime >= parseInt(autoLogoutSecondAlarm) + secondAlarmTime + lastAlarmTime) {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
localStorage.removeItem('autoLogoutSecondAlarm');
} else {
const timeGone = currentTime - parseInt(autoLogoutSecondAlarm);
const remainTime = secondAlarmTime - timeGone;
dispatch(setLoginState());
setAutoLogoutAlarm(dispatch, 'second', remainTime, lastAlarmTime);
}
if (currentTime >= parseInt(autoLogoutSecondAlarm) + secondAlarmTime) {
requestNewAccessToken().then(newAccessToken => {
if (newAccessToken) {
localStorage.setItem('accessToken', `Bearer ${newAccessToken}`);
dispatch(setLoginState());
setAutoLogoutAlarm(dispatch, 'second', secondAlarmTime, lastAlarmTime);
} else {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
localStorage.removeItem('autoLogoutSecondAlarm');
}
});
}
}

if (autoLogoutLastAlarm !== null) {
if (currentTime >= parseInt(autoLogoutLastAlarm) + lastAlarmTime) {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
localStorage.removeItem('autoLogoutLastAlarm');
} else {
const timeGone = currentTime - parseInt(autoLogoutLastAlarm);
const remainTime = lastAlarmTime - timeGone;
dispatch(setLoginState());
setAutoLogoutAlarm(dispatch, 'last', remainTime);
}
requestNewAccessToken().then(newAccessToken => {
if (newAccessToken) {
localStorage.setItem('accessToken', `Bearer ${newAccessToken}`);
dispatch(setLoginState());
setAutoLogoutAlarm(dispatch, 'last', lastAlarmTime);
} else {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
localStorage.removeItem('autoLogoutLastAlarm');
}
});
}
}
}
}, [dispatch]);
Expand Down
120 changes: 73 additions & 47 deletions client/src/hooks/customHooks/useOAuthLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,58 +5,84 @@ import setAutoLogoutAlarm from '../../utils/setAutoLogoutAlarm';
import { secondAlarmTime, lastAlarmTime } from '../../utils/setAutoLogoutAlarm';

const useOAuthLogin = () => {
const dispatch = useDispatch();

useEffect(() => {
const urlParams = new URLSearchParams(window.location.search);
const accessToken = urlParams.get('access_token');
const refreshToken = urlParams.get('refresh_token');
const currentTime = Date.now();
const autoLogoutSecondAlarm = localStorage.getItem('autoLogoutSecondAlarm');
const autoLogoutLastAlarm = localStorage.getItem('autoLogoutLastAlarm');

if (accessToken && refreshToken) {
localStorage.setItem('accessToken', `Bearer ${accessToken}`);
localStorage.setItem('refreshToken', refreshToken);

urlParams.delete('access_token');
urlParams.delete('refresh_token');
window.history.replaceState({}, '', '?' + urlParams.toString());

if (autoLogoutSecondAlarm === null) {
dispatch(setLoginState()); // 로그인 처리
setAutoLogoutAlarm(dispatch, 'first', secondAlarmTime, lastAlarmTime);
}

if (autoLogoutSecondAlarm !== null) {
if (currentTime >= parseInt(autoLogoutSecondAlarm) + secondAlarmTime + lastAlarmTime) {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
localStorage.removeItem('autoLogoutSecondAlarm');
} else {
const timeGone = currentTime - parseInt(autoLogoutSecondAlarm);
const remainTime = secondAlarmTime - timeGone
dispatch(setLoginState()); // 로그인 처리
setAutoLogoutAlarm(dispatch, 'second', remainTime, lastAlarmTime);
const dispatch = useDispatch();

// 리프레시 토큰을 사용하여 새 엑세스 토큰을 요청하는 함수
const requestNewAccessToken = async () => {
const refreshToken = localStorage.getItem("refreshToken");
try {
const response = await fetch('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/tokens/refresh', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ refreshToken: refreshToken })
});

if (response.status !== 201) {
throw new Error('Failed to fetch new access token');
}

const data = await response.json();
return data.accessToken;
} catch (error) {
console.error(error);
return null;
}
}
};

useEffect(() => {
const urlParams = new URLSearchParams(window.location.search);
const accessToken = urlParams.get('access_token');
const refreshToken = urlParams.get('refresh_token');

if (autoLogoutLastAlarm !== null) {
if (currentTime >= parseInt(autoLogoutLastAlarm) + lastAlarmTime) {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
localStorage.removeItem('autoLogoutLastAlarm');
if (accessToken && refreshToken) {
localStorage.setItem('accessToken', `Bearer ${accessToken}`);
localStorage.setItem('refreshToken', refreshToken);

urlParams.delete('access_token');
urlParams.delete('refresh_token');
window.history.replaceState({}, '', '?' + urlParams.toString());

dispatch(setLoginState()); // 로그인 처리
setAutoLogoutAlarm(dispatch, 'first', secondAlarmTime, lastAlarmTime);
} else {
const timeGone = currentTime - parseInt(autoLogoutLastAlarm);
const remainTime = lastAlarmTime - timeGone;
dispatch(setLoginState()); // 로그인 처리
setAutoLogoutAlarm(dispatch, 'last', remainTime);
const storedAccessToken = localStorage.getItem('accessToken');
const currentTime = Date.now();
const autoLogoutSecondAlarm = localStorage.getItem('autoLogoutSecondAlarm');
const autoLogoutLastAlarm = localStorage.getItem('autoLogoutLastAlarm');

if (storedAccessToken) {
if (autoLogoutSecondAlarm && currentTime >= parseInt(autoLogoutSecondAlarm) + secondAlarmTime) {
requestNewAccessToken().then(newAccessToken => {
if (newAccessToken) {
localStorage.setItem('accessToken', `Bearer ${newAccessToken}`);
dispatch(setLoginState());
} else {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
localStorage.removeItem('autoLogoutSecondAlarm');
}
});
}

if (autoLogoutLastAlarm && currentTime >= parseInt(autoLogoutLastAlarm) + lastAlarmTime) {
requestNewAccessToken().then(newAccessToken => {
if (newAccessToken) {
localStorage.setItem('accessToken', `Bearer ${newAccessToken}`);
dispatch(setLoginState());
} else {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
localStorage.removeItem('autoLogoutLastAlarm');
}
});
}
}
}
}
}
}, [dispatch]);
}, [dispatch]);

return;
return;
};

export default useOAuthLogin;
162 changes: 68 additions & 94 deletions client/src/utils/setAutoLogoutAlarm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,107 +20,81 @@ export const secondAlarmTime = 1000 * 60 * 29; // 29분
export const lastAlarmTime = 1000 * 60; // 1분

const setAutoLogoutAlarm = (dispatch: any, alarmNum: string, secondAlarmTime: number, lastAlarmTime?: number) => {
// 1~3차 알림 모두 설정
if (alarmNum === alarmNumType.First) {
toast.warning("로그인 상태는 30분 동안 유지됩니다", {
style: toastStyle,
position: "top-center",
});

// 2차 알림 셋팅 시간 기록
const autoLogoutSecondAlarm = Date.now();
localStorage.setItem("autoLogoutSecondAlarm", `${autoLogoutSecondAlarm}`);

setTimeout(() => {
// 2차 알림 셋팅 시간 제거
localStorage.removeItem("autoLogoutSecondAlarm");

toast.warning("1분 뒤 로그아웃 처리됩니다", {
style: toastStyle,
position: "top-center",
});

// 3차 알림 셋팅 시간 기록
const autoLogoutLastAlarm = Date.now();
localStorage.setItem("autoLogoutLastAlarm", `${autoLogoutLastAlarm}`);

setTimeout(() => {
// 3차 알림 셋팅 시간 제거
localStorage.removeItem("autoLogoutLastAlarm");

dispatch(setLogoutState());
localStorage.removeItem("accessToken");
localStorage.removeItem("refreshToken");

toast.warning("로그아웃 처리되었습니다", {
style: toastStyle,
position: "top-center",
// 리프레시 토큰을 사용하여 새 엑세스 토큰을 요청하는 함수
const requestNewAccessToken = async () => {
const refreshToken = localStorage.getItem("refreshToken");
try {
const response = await fetch('http://ec2-13-125-246-160.ap-northeast-2.compute.amazonaws.com:8080/tokens/refresh', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ refreshToken: refreshToken })
});

if (response.status !== 201) {
throw new Error('Failed to fetch new access token');
}

const data = await response.json();
return data.accessToken;
} catch (error) {
console.error(error);
return null;
}
};

const handleTokenRefresh = async () => {
const newAccessToken = await requestNewAccessToken();

if (newAccessToken) {
sessionStorage.setItem("accessToken", `Bearer ${newAccessToken}`);
toast.success("로그인이 연장되었습니다", { style: toastStyle, position: "top-center" });
} else {
dispatch(setLogoutState());
localStorage.removeItem("accessToken");
localStorage.removeItem("refreshToken");
toast.warning("로그아웃 처리되었습니다", { style: toastStyle, position: "top-center" });
}
};

if (alarmNum === alarmNumType.First) {
toast.warning("로그인 상태는 30분 동안 유지됩니다", {
style: toastStyle,
position: "top-center",
});
}, lastAlarmTime);
}, secondAlarmTime);
}

// 2~3차 알림 설정
if (alarmNum === alarmNumType.Second) {
setTimeout(() => {
// 2차 알림 셋팅 시간 제거
localStorage.removeItem("autoLogoutSecondAlarm");

toast.warning("1분 뒤 로그아웃 처리됩니다", {
style: toastStyle,
position: "top-center",
});

// 3차 알림 셋팅 시간 기록
const autoLogoutLastAlarm = Date.now();
localStorage.setItem("autoLogoutLastAlarm", `${autoLogoutLastAlarm}`);

setTimeout(() => {
// 3차 알림 셋팅 시간 제거
localStorage.removeItem("autoLogoutLastAlarm");

dispatch(setLogoutState());
localStorage.removeItem("accessToken");
localStorage.removeItem("refreshToken");

toast.warning("로그아웃 처리되었습니다", {
style: toastStyle,
position: "top-center",
});
}, lastAlarmTime);
}, secondAlarmTime);

return;
}

// 3차 알림만 설정
if (alarmNum === alarmNumType.Last) {
setTimeout(() => {
// 3차 알림 셋팅 시간 제거
localStorage.removeItem("autoLogoutLastAlarm");

dispatch(setLogoutState());
localStorage.removeItem("accessToken");
localStorage.removeItem("refreshToken");

toast.warning("로그아웃 처리되었습니다", {
style: toastStyle,
position: "top-center",
});
}, lastAlarmTime);
}

const autoLogoutSecondAlarm = Date.now();
localStorage.setItem("autoLogoutSecondAlarm", `${autoLogoutSecondAlarm}`);

setTimeout(handleTokenRefresh, secondAlarmTime);
}

if (alarmNum === alarmNumType.Second) {
setTimeout(handleTokenRefresh, secondAlarmTime);
}

// 3차 알림만 설정
if (alarmNum === alarmNumType.Last) {
setTimeout(() => {
dispatch(setLogoutState());
localStorage.removeItem("accessToken");
localStorage.removeItem("refreshToken");
toast.warning("로그아웃 처리되었습니다", { style: toastStyle, position: "top-center" });
}, lastAlarmTime);
}
};

export default setAutoLogoutAlarm;

const alarmNumType = {
First: "first",
Second: "second",
Last: "last",
First: "first",
Second: "second",
Last: "last",
};

const toastStyle = {
fontSize: "15px",
fontWeight: 350,
color: "black",
fontSize: "15px",
fontWeight: 350,
color: "black",
};