anzar 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/http/jwt_interceptor.ts +117 -13
package/package.json
CHANGED
|
@@ -1,16 +1,43 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
AxiosError,
|
|
3
|
+
AxiosInstance,
|
|
4
|
+
InternalAxiosRequestConfig,
|
|
5
|
+
} from "axios";
|
|
6
|
+
import type { AuthResponse } from "../types/auth";
|
|
7
|
+
import { type Token, TokenType } from "../types/token";
|
|
8
|
+
|
|
9
|
+
const ENDPOINTS = new Map([
|
|
10
|
+
["/auth/login", null],
|
|
11
|
+
["/auth/register", null],
|
|
12
|
+
["/auth/refreshToken", TokenType.RefreshToken],
|
|
13
|
+
["/auth/logout", TokenType.RefreshToken],
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
const endpointConfig: Record<string, TokenType | null> = {
|
|
17
|
+
"/auth/login": null,
|
|
18
|
+
"/auth/register": null,
|
|
19
|
+
"/auth/refreshToken": TokenType.RefreshToken,
|
|
20
|
+
"/auth/logout": TokenType.RefreshToken,
|
|
21
|
+
};
|
|
3
22
|
|
|
4
23
|
export class JwtInterceptor {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
24
|
+
// TODO add AnzarConfig as an arg to apply
|
|
25
|
+
apply(axiosInstance: AxiosInstance) {
|
|
26
|
+
function _extractTokenFromCache(tokenType: TokenType): Token | null {
|
|
27
|
+
const token = localStorage.getItem(tokenType.toString());
|
|
28
|
+
|
|
29
|
+
return token ? ({ value: token, tokenType } as Token) : null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
axiosInstance.interceptors.request.use(
|
|
8
33
|
(config) => {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
34
|
+
const url = config.url;
|
|
35
|
+
if (!url) return config;
|
|
36
|
+
const tokenType = endpointConfig[url] ?? TokenType.AccessToken;
|
|
37
|
+
const token = tokenType ? _extractTokenFromCache(tokenType) : null;
|
|
38
|
+
|
|
39
|
+
if (token) {
|
|
40
|
+
config.headers.Authorization = `Bearer ${token}`;
|
|
14
41
|
}
|
|
15
42
|
|
|
16
43
|
return config;
|
|
@@ -21,8 +48,85 @@ export class JwtInterceptor {
|
|
|
21
48
|
},
|
|
22
49
|
);
|
|
23
50
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
51
|
+
axiosInstance.interceptors.response.use(
|
|
52
|
+
(response) => {
|
|
53
|
+
const url = response.config.url;
|
|
54
|
+
if (!url) return response;
|
|
55
|
+
|
|
56
|
+
if (url === "/auth/logout") {
|
|
57
|
+
localStorage.removeItem(TokenType.AccessToken.toString());
|
|
58
|
+
localStorage.removeItem(TokenType.RefreshToken.toString());
|
|
59
|
+
return response;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const value = ENDPOINTS.get(url);
|
|
63
|
+
const token_type = value === undefined ? TokenType.AccessToken : value;
|
|
64
|
+
|
|
65
|
+
if (token_type === TokenType.AccessToken) {
|
|
66
|
+
return response;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const auth_response: AuthResponse = response.data;
|
|
70
|
+
|
|
71
|
+
if (auth_response.tokens) {
|
|
72
|
+
localStorage.setItem(
|
|
73
|
+
TokenType.AccessToken.toString(),
|
|
74
|
+
auth_response.tokens.access,
|
|
75
|
+
);
|
|
76
|
+
localStorage.setItem(
|
|
77
|
+
TokenType.RefreshToken.toString(),
|
|
78
|
+
auth_response.tokens.refresh,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return response;
|
|
83
|
+
},
|
|
84
|
+
async (error: AxiosError) => {
|
|
85
|
+
const originalRequest = error.config as InternalAxiosRequestConfig & {
|
|
86
|
+
_retry?: boolean;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// const value = ENDPOINTS.get(error.request.url);
|
|
90
|
+
// const token_type = value === undefined ? TokenType.AccessToken : value;
|
|
91
|
+
// if (error.status === 401 && token_type === TokenType.AccessToken) {
|
|
92
|
+
|
|
93
|
+
if (error.response?.status === 401 && !originalRequest._retry) {
|
|
94
|
+
originalRequest._retry = true;
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
const refreshToken = localStorage.getItem(
|
|
98
|
+
TokenType.RefreshToken.toString(),
|
|
99
|
+
);
|
|
100
|
+
const response = await axiosInstance.post(
|
|
101
|
+
"/auth/refreshToken",
|
|
102
|
+
{},
|
|
103
|
+
{ headers: { authorization: `Bearer ${refreshToken}` } },
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const auth_response: AuthResponse = response.data;
|
|
107
|
+
if (auth_response.tokens) {
|
|
108
|
+
localStorage.setItem(
|
|
109
|
+
TokenType.AccessToken.toString(),
|
|
110
|
+
auth_response.tokens.access,
|
|
111
|
+
);
|
|
112
|
+
localStorage.setItem(
|
|
113
|
+
TokenType.RefreshToken.toString(),
|
|
114
|
+
auth_response.tokens.refresh,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Retry original request with new token
|
|
119
|
+
originalRequest.headers.Authorization = `Bearer ${auth_response.tokens?.access}`;
|
|
120
|
+
return axiosInstance(originalRequest);
|
|
121
|
+
} catch (e) {
|
|
122
|
+
localStorage.clear();
|
|
123
|
+
window.location.href = "/";
|
|
124
|
+
return Promise.reject(e);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return Promise.reject(error);
|
|
129
|
+
},
|
|
130
|
+
);
|
|
27
131
|
}
|
|
28
132
|
}
|