feat: Refresh token on load and user information added
This commit is contained in:
@@ -1,8 +1,31 @@
|
||||
// useAuth.tsx
|
||||
import { AuthContext } from '@/contexts/AuthContext';
|
||||
import { AuthContext, type UserInfo } from '@/contexts/AuthContext';
|
||||
import type { GenerateTokenResponse } from '@/features/authorization/api/identityAPI';
|
||||
import axios from 'axios';
|
||||
import { useEffect, useState, type ReactNode } from 'react';
|
||||
import { jwtDecode } from 'jwt-decode';
|
||||
import type { GUID } from '@/types/commonTypes';
|
||||
|
||||
export interface AccessTokenJwtPayload {
|
||||
iss: string;
|
||||
nbf: number;
|
||||
iat: number;
|
||||
exp: number;
|
||||
scope: string[];
|
||||
amr: string[];
|
||||
client_id: string;
|
||||
sub: GUID;
|
||||
auth_time: number;
|
||||
idp: string;
|
||||
picture: string;
|
||||
given_name: string;
|
||||
family_name: string;
|
||||
email: string;
|
||||
name: string;
|
||||
phone_number: string;
|
||||
session: GUID;
|
||||
jti: string;
|
||||
}
|
||||
|
||||
export const ACCESS_TOKEN_KEY: 'access_token' = 'access_token' as const;
|
||||
export const REFRESH_TOKEN_KEY: 'refresh_token' = 'refresh_token' as const;
|
||||
@@ -12,20 +35,31 @@ let inMemoryToken: string | null = null;
|
||||
let expiresAt = 0;
|
||||
|
||||
export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
||||
const [userInfo, setUserInfo] = useState<UserInfo | null>(null);
|
||||
const [authFinished, setAuthFinished] = useState<boolean>(false);
|
||||
const [accessToken, setAccessToken] = useState<string | null>(
|
||||
sessionStorage.getItem(ACCESS_TOKEN_KEY),
|
||||
);
|
||||
|
||||
// Initialize from sessionStorage (page reload)
|
||||
useEffect(() => {
|
||||
const token = sessionStorage.getItem(ACCESS_TOKEN_KEY);
|
||||
const exp = Number(sessionStorage.getItem(EXPIRES_IN_KEY) || 0);
|
||||
const handleAndSetToken = async () => {
|
||||
const token = sessionStorage.getItem(ACCESS_TOKEN_KEY);
|
||||
|
||||
if (token && Date.now() < exp) {
|
||||
inMemoryToken = token;
|
||||
expiresAt = exp;
|
||||
setAccessToken(token);
|
||||
}
|
||||
if (token) {
|
||||
setUserInfoFromToken(token);
|
||||
await refreshAccessToken();
|
||||
inMemoryToken = token;
|
||||
expiresAt = Number(sessionStorage.getItem(EXPIRES_IN_KEY) || 0);
|
||||
setAccessToken(token);
|
||||
|
||||
setAuthFinished(true);
|
||||
}
|
||||
|
||||
setAuthFinished(true);
|
||||
};
|
||||
|
||||
handleAndSetToken();
|
||||
}, []);
|
||||
|
||||
// Background refresh
|
||||
@@ -38,8 +72,6 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
||||
setAccessToken(inMemoryToken);
|
||||
};
|
||||
|
||||
handleRefreshTokenIfNeeded();
|
||||
|
||||
const interval = setInterval(async () => {
|
||||
await handleRefreshTokenIfNeeded();
|
||||
}, 30_000);
|
||||
@@ -100,6 +132,7 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
||||
expiresAt = Date.now() + result.data.expires_in * 1000;
|
||||
|
||||
sessionStorage.setItem(ACCESS_TOKEN_KEY, inMemoryToken as string);
|
||||
sessionStorage.setItem(REFRESH_TOKEN_KEY, result.data.refresh_token);
|
||||
sessionStorage.setItem(EXPIRES_IN_KEY, String(expiresAt));
|
||||
|
||||
setAccessToken(inMemoryToken);
|
||||
@@ -111,8 +144,26 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
||||
}
|
||||
}
|
||||
|
||||
function setUserInfoFromToken(token: string) {
|
||||
const accessTokenPayload = jwtDecode<AccessTokenJwtPayload>(token);
|
||||
|
||||
const userInfo: UserInfo = {
|
||||
picture: accessTokenPayload.picture,
|
||||
firstName: accessTokenPayload.given_name,
|
||||
lastName: accessTokenPayload.family_name,
|
||||
fullName: accessTokenPayload.name,
|
||||
email: accessTokenPayload.email,
|
||||
phoneNumber: accessTokenPayload.phone_number,
|
||||
userID: accessTokenPayload.sub,
|
||||
};
|
||||
|
||||
setUserInfo(userInfo);
|
||||
}
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ accessToken, getToken, login, logout }}>
|
||||
<AuthContext.Provider
|
||||
value={{ accessToken, getToken, login, logout, authFinished, userInfo }}
|
||||
>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user