mirror of
https://github.com/bubblecup-12/VogelSocialMedia.git
synced 2025-07-10 13:18:48 +00:00
tokens refresh when jwt is expired and added basic axios config
This commit is contained in:
parent
36366d8814
commit
dc02a2ae52
15 changed files with 470 additions and 289 deletions
94
code/frontend/src/api/Auth.tsx
Normal file
94
code/frontend/src/api/Auth.tsx
Normal file
|
@ -0,0 +1,94 @@
|
|||
import {
|
||||
createContext,
|
||||
useContext,
|
||||
useState,
|
||||
ReactNode,
|
||||
FC,
|
||||
useEffect,
|
||||
} from "react";
|
||||
import api from "./axios";
|
||||
import { jwtDecode } from "jwt-decode";
|
||||
import { redirectToLogin } from "./axios";
|
||||
import { refreshToken } from "./refreshToken";
|
||||
|
||||
type User = {
|
||||
id: string;
|
||||
username: string;
|
||||
role: string;
|
||||
};
|
||||
|
||||
type AuthContextType = {
|
||||
user: User | null;
|
||||
logout: () => Promise<void>;
|
||||
setUserState: (tryRefresh?: boolean) => Promise<void>;
|
||||
};
|
||||
type JwtPayload = {
|
||||
username: string;
|
||||
role: string;
|
||||
sub: string;
|
||||
jti: string;
|
||||
iat: number;
|
||||
exp: number;
|
||||
iss: string;
|
||||
};
|
||||
|
||||
const AuthContext = createContext<AuthContextType | null>(null);
|
||||
|
||||
type AuthProviderProps = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
export const Auth: FC<AuthProviderProps> = ({ children }) => {
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
useEffect(() => {
|
||||
setUserState();
|
||||
}, []);
|
||||
|
||||
const setUserState = async (tryRefresh = true) => {
|
||||
try {
|
||||
const token = localStorage.getItem("token");
|
||||
if (!token) return;
|
||||
const now = Date.now() / 1000;
|
||||
const decoded = jwtDecode<JwtPayload>(token);
|
||||
|
||||
if (decoded.exp > now) {
|
||||
setUser({
|
||||
id: decoded.sub,
|
||||
username: decoded.username,
|
||||
role: decoded.role,
|
||||
});
|
||||
} else if (tryRefresh) {
|
||||
await refreshToken();
|
||||
await setUserState(false);
|
||||
}
|
||||
} catch {
|
||||
console.log("Error while reading and refreshing user info"); // this error should only appear if the app is run in strictMode
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const logout = async () => {
|
||||
try {
|
||||
await api.delete("/user/logout");
|
||||
} catch {
|
||||
console.log("Logout error");
|
||||
}
|
||||
localStorage.clear();
|
||||
setUser(null);
|
||||
redirectToLogin(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ user, logout, setUserState }}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useAuth = (): AuthContextType => {
|
||||
const ctx = useContext(AuthContext);
|
||||
if (!ctx) {
|
||||
throw new Error("useAuth must be used within an AuthProvider");
|
||||
}
|
||||
return ctx;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue