feat: Refresh Token for improved Session Security (#927)

* feat(api): refresh token logic

* feat(client): refresh token logic

* feat(data-provider): refresh token logic

* fix: SSE uses esm

* chore: add default refresh token expiry to AuthService, add message about env var not set when generating a token

* chore: update scripts to more compatible bun methods, ran bun install again

* chore: update env.example and playwright workflow with JWT_REFRESH_SECRET

* chore: update breaking changes docs

* chore: add timeout to url visit

* chore: add default SESSION_EXPIRY in generateToken logic, add act script for testing github actions

* fix(e2e): refresh automatically in development environment to pass e2e tests
This commit is contained in:
Danny Avila 2023-09-11 13:10:46 -04:00 committed by GitHub
parent 75be9a3279
commit 33f087d38f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 420 additions and 232 deletions

View file

@ -107,12 +107,7 @@ const AuthContextProvider = ({
});
};
const logout = () => {
document.cookie.split(';').forEach((c) => {
document.cookie = c
.replace(/^ +/, '')
.replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/');
});
const logout = useCallback(() => {
logoutUser.mutate(undefined, {
onSuccess: () => {
setUserContext({
@ -126,7 +121,25 @@ const AuthContextProvider = ({
doSetError((error as Error).message);
},
});
};
}, [setUserContext, logoutUser]);
const silentRefresh = useCallback(() => {
refreshToken.mutate(undefined, {
onSuccess: (data: TLoginResponse) => {
const { user, token } = data;
if (token) {
setUserContext({ token, isAuthenticated: true, user });
} else {
console.log('Token is not present. User is not authenticated.');
navigate('/login');
}
},
onError: (error) => {
console.log('refreshToken mutation error:', error);
navigate('/login');
},
});
}, []);
useEffect(() => {
if (userQuery.data) {
@ -139,12 +152,7 @@ const AuthContextProvider = ({
doSetError(undefined);
}
if (!token || !isAuthenticated) {
const tokenFromCookie = getCookieValue('token');
if (tokenFromCookie) {
setUserContext({ token: tokenFromCookie, isAuthenticated: true, user: userQuery.data });
} else {
navigate('/login', { replace: true });
}
silentRefresh();
}
}, [
token,
@ -157,23 +165,23 @@ const AuthContextProvider = ({
setUserContext,
]);
// const silentRefresh = useCallback(() => {
// refreshToken.mutate(undefined, {
// onSuccess: (data: TLoginResponse) => {
// const { user, token } = data;
// setUserContext({ token, isAuthenticated: true, user });
// },
// onError: error => {
// setError(error.message);
// }
// });
//
// }, [setUserContext]);
useEffect(() => {
const handleTokenUpdate = (event) => {
console.log('tokenUpdated event received event');
const newToken = event.detail;
setUserContext({
token: newToken,
isAuthenticated: true,
user: user,
});
};
// useEffect(() => {
// if (token)
// silentRefresh();
// }, [token, silentRefresh]);
window.addEventListener('tokenUpdated', handleTokenUpdate);
return () => {
window.removeEventListener('tokenUpdated', handleTokenUpdate);
};
}, [setUserContext, user]);
// Make the provider update only when it should
const memoedValue = useMemo(