This repository has been archived by the owner on Dec 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
AuthContext.tsx
108 lines (87 loc) · 3.64 KB
/
AuthContext.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import axios, { AxiosInstance } from "axios";
import React, { createContext, useEffect, useState } from "react";
import { ApolloClient, ApolloProvider, NormalizedCacheObject } from "@apollo/client";
import { authByProvidersToken, refreshToken as refreshApiToken } from "../../api/rest/auth/Auth";
import { AuthResponse } from "../../api/rest/auth/AuthResponse.interface";
import { createAxiosClient } from "./axiosService";
import { createApolloClient } from "./apolloService";
import Providers from "../../api/rest/auth/oauth/Provider";
import { User } from "../../common/models/User";
export interface AuthContextInterface {
auth(provider: string, code: string, state?: string): Promise<User>
logout(): void
user?: User
refreshSession(): void
axios: AxiosInstance
}
export const AuthContext = createContext<AuthContextInterface>({
auth: async () => { throw new Error("AuthContext not initialized") },
logout: () => { throw new Error("AuthContext not initialized") },
refreshSession: () => { throw new Error("AuthContext not initialized") },
axios: axios.create({baseURL: __RESTAPI_URI__})
});
export const AuthContextProvider: React.FC = ({ children }) => {
const [user, setUser] = useState<User|undefined>(undefined);
const [axiosClient, setAxiosClient] = useState<AxiosInstance>(() => createAxiosClient());
const [apolloClient, setApolloClient] = useState<ApolloClient<NormalizedCacheObject>>(() => createApolloClient());
/**
* Update rest authorization header, decode user, save refresh_token
* @param authRes auth request's response
*/
const handleAuth = (authRes: AuthResponse): User => {
axiosClient.defaults.withCredentials = true;
axiosClient.defaults.headers.common["Authorization"] = "Bearer " + authRes.accessToken;
//todo: modify existing instance
setApolloClient(() => createApolloClient({
headers: {
["Authorization"]: "Bearer " + authRes.accessToken,
}
}));
localStorage.setItem("refresh_token", authRes.refreshToken);
const userModel = User.fromResponse(authRes.user)
setUser(() => userModel);
return userModel;
}
const auth = async (provider: Providers, code: string, state?: string): Promise<User> => {
const authRes = await authByProvidersToken(axiosClient, provider, code, state);
if (!authRes)
throw new Error("Auth failed!");
return handleAuth(authRes);
}
const logout = () => {
setApolloClient(() => createApolloClient());
setAxiosClient(() => createAxiosClient());
setUser(() => undefined);
localStorage.setItem("refresh_token", "");
}
const refreshToken = () => {
const refresh_token = localStorage.getItem("refresh_token");
if (refresh_token && refresh_token != "undefined")
refreshApiToken(axiosClient, refresh_token)
.then(handleAuth)
.catch((err) => {
console.error(err)
localStorage.removeItem("refresh_token");
})
else
localStorage.removeItem("refresh_token");
}
// get token at app start
useEffect(() => {
refreshToken();
}, []);
return (
<ApolloProvider client={apolloClient}>
<AuthContext.Provider
value={{
auth,
logout,
user,
refreshSession: refreshToken,
axios: axiosClient
}}>
{children}
</AuthContext.Provider>
</ApolloProvider>
)
};