dauth-context-react 1.0.3 → 2.1.0
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/dist/api/dauth.api.d.ts +5 -6
- package/dist/api/interfaces/dauth.api.responses.d.ts +3 -3
- package/dist/constants.d.ts +1 -0
- package/dist/dauth-context-react.cjs.development.js +325 -322
- package/dist/dauth-context-react.cjs.development.js.map +1 -1
- package/dist/dauth-context-react.cjs.production.min.js +1 -1
- package/dist/dauth-context-react.cjs.production.min.js.map +1 -1
- package/dist/dauth-context-react.esm.js +326 -323
- package/dist/dauth-context-react.esm.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/interfaces.d.ts +4 -1
- package/dist/reducer/dauth.actions.d.ts +11 -11
- package/package.json +1 -1
- package/src/api/dauth.api.ts +24 -16
- package/src/api/interfaces/dauth.api.responses.ts +3 -3
- package/src/constants.ts +1 -0
- package/src/index.tsx +69 -80
- package/src/interfaces.ts +4 -9
- package/src/reducer/dauth.actions.ts +82 -78
package/src/interfaces.ts
CHANGED
|
@@ -13,6 +13,9 @@ export interface IDauthUser {
|
|
|
13
13
|
role: string;
|
|
14
14
|
telPrefix: string;
|
|
15
15
|
telSuffix: string;
|
|
16
|
+
birthDate?: Date;
|
|
17
|
+
country?: string;
|
|
18
|
+
metadata?: Record<string, unknown>;
|
|
16
19
|
createdAt: Date;
|
|
17
20
|
updatedAt: Date;
|
|
18
21
|
lastLogin: Date;
|
|
@@ -32,15 +35,7 @@ export interface IDauthState {
|
|
|
32
35
|
loginWithRedirect: () => void;
|
|
33
36
|
logout: () => void;
|
|
34
37
|
getAccessToken: () => Promise<string>;
|
|
35
|
-
updateUser: (
|
|
36
|
-
name,
|
|
37
|
-
lastname,
|
|
38
|
-
nickname,
|
|
39
|
-
telPrefix,
|
|
40
|
-
telSuffix,
|
|
41
|
-
language,
|
|
42
|
-
avatar,
|
|
43
|
-
}: Partial<IDauthUser>) => Promise<boolean>;
|
|
38
|
+
updateUser: (fields: Partial<IDauthUser>) => Promise<boolean>;
|
|
44
39
|
updateUserWithRedirect: () => void;
|
|
45
40
|
// Send email verification
|
|
46
41
|
sendEmailVerificationStatus: {
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getUserAPI,
|
|
3
|
-
|
|
3
|
+
logoutAPI,
|
|
4
|
+
refreshTokenAPI,
|
|
4
5
|
sendEmailVerificationAPI,
|
|
5
6
|
updateUserAPI,
|
|
6
7
|
} from '../api/dauth.api';
|
|
7
|
-
import {
|
|
8
|
-
import { TOKEN_LS } from '../constants';
|
|
8
|
+
import { TOKEN_LS, REFRESH_TOKEN_LS } from '../constants';
|
|
9
9
|
import { IDauthDomainState, IDauthUser } from '../interfaces';
|
|
10
|
-
import { routes } from '../api/utils/routes';
|
|
11
10
|
import * as DauthTypes from './dauth.types';
|
|
12
11
|
|
|
13
12
|
type TSetDauthStateAction = {
|
|
14
13
|
dispatch: React.Dispatch<any>;
|
|
15
14
|
token: string;
|
|
15
|
+
refreshToken: string;
|
|
16
16
|
domainName: string;
|
|
17
17
|
};
|
|
18
18
|
export async function setDauthStateAction({
|
|
19
19
|
dispatch,
|
|
20
20
|
token,
|
|
21
|
+
refreshToken,
|
|
21
22
|
domainName,
|
|
22
23
|
}: TSetDauthStateAction) {
|
|
23
24
|
dispatch({ type: DauthTypes.SET_IS_LOADING, payload: { isLoading: true } });
|
|
@@ -33,7 +34,9 @@ export async function setDauthStateAction({
|
|
|
33
34
|
},
|
|
34
35
|
});
|
|
35
36
|
window.history.replaceState({}, document.title, window.location.pathname);
|
|
36
|
-
|
|
37
|
+
localStorage.setItem(TOKEN_LS, token);
|
|
38
|
+
localStorage.setItem(REFRESH_TOKEN_LS, refreshToken);
|
|
39
|
+
return;
|
|
37
40
|
} else {
|
|
38
41
|
return resetUser(dispatch);
|
|
39
42
|
}
|
|
@@ -50,23 +53,29 @@ export async function setDauthStateAction({
|
|
|
50
53
|
|
|
51
54
|
type TSetAutoLoginAction = {
|
|
52
55
|
dispatch: React.Dispatch<any>;
|
|
53
|
-
token_ls: string;
|
|
54
56
|
domainName: string;
|
|
55
57
|
};
|
|
56
58
|
export async function setAutoLoginAction({
|
|
57
59
|
dispatch,
|
|
58
|
-
token_ls,
|
|
59
60
|
domainName,
|
|
60
61
|
}: TSetAutoLoginAction) {
|
|
61
62
|
dispatch({ type: DauthTypes.SET_IS_LOADING, payload: { isLoading: true } });
|
|
63
|
+
const storedRefreshToken = localStorage.getItem(REFRESH_TOKEN_LS);
|
|
64
|
+
if (!storedRefreshToken) {
|
|
65
|
+
dispatch({
|
|
66
|
+
type: DauthTypes.SET_IS_LOADING,
|
|
67
|
+
payload: { isLoading: false },
|
|
68
|
+
});
|
|
69
|
+
return resetUser(dispatch);
|
|
70
|
+
}
|
|
62
71
|
try {
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const getUserFetch = await getUserAPI(domainName,
|
|
72
|
+
const refreshResult = await refreshTokenAPI(domainName, storedRefreshToken);
|
|
73
|
+
if (refreshResult.response.status === 200) {
|
|
74
|
+
const newAccessToken = refreshResult.data.accessToken;
|
|
75
|
+
const newRefreshToken = refreshResult.data.refreshToken;
|
|
76
|
+
localStorage.setItem(TOKEN_LS, newAccessToken);
|
|
77
|
+
localStorage.setItem(REFRESH_TOKEN_LS, newRefreshToken);
|
|
78
|
+
const getUserFetch = await getUserAPI(domainName, newAccessToken);
|
|
70
79
|
if (getUserFetch.response.status === 200) {
|
|
71
80
|
dispatch({
|
|
72
81
|
type: DauthTypes.LOGIN,
|
|
@@ -76,26 +85,14 @@ export async function setAutoLoginAction({
|
|
|
76
85
|
isAuthenticated: true,
|
|
77
86
|
},
|
|
78
87
|
});
|
|
79
|
-
localStorage.setItem(
|
|
80
|
-
TOKEN_LS,
|
|
81
|
-
refreshAccessTokenFetch.data.accessToken
|
|
82
|
-
);
|
|
83
88
|
return;
|
|
84
|
-
} else {
|
|
85
|
-
window.location.replace(
|
|
86
|
-
`${getClientBasePath()}/${domainName}/${routes.signin}`
|
|
87
|
-
);
|
|
88
|
-
return resetUser(dispatch);
|
|
89
89
|
}
|
|
90
|
-
} else {
|
|
91
|
-
window.location.replace(
|
|
92
|
-
`${getClientBasePath()}/${domainName}/${routes.signin}`
|
|
93
|
-
);
|
|
94
|
-
return resetUser(dispatch);
|
|
95
90
|
}
|
|
91
|
+
// Refresh failed — session expired
|
|
92
|
+
resetUser(dispatch);
|
|
96
93
|
} catch (error) {
|
|
97
94
|
console.error(error);
|
|
98
|
-
|
|
95
|
+
resetUser(dispatch);
|
|
99
96
|
} finally {
|
|
100
97
|
dispatch({
|
|
101
98
|
type: DauthTypes.SET_IS_LOADING,
|
|
@@ -104,29 +101,67 @@ export async function setAutoLoginAction({
|
|
|
104
101
|
}
|
|
105
102
|
}
|
|
106
103
|
|
|
107
|
-
export function setLogoutAction({
|
|
104
|
+
export async function setLogoutAction({
|
|
108
105
|
dispatch,
|
|
106
|
+
domainName,
|
|
109
107
|
}: {
|
|
110
108
|
dispatch: React.Dispatch<any>;
|
|
109
|
+
domainName: string;
|
|
111
110
|
}) {
|
|
111
|
+
const storedRefreshToken = localStorage.getItem(REFRESH_TOKEN_LS);
|
|
112
|
+
if (storedRefreshToken && domainName) {
|
|
113
|
+
try {
|
|
114
|
+
await logoutAPI(domainName, storedRefreshToken);
|
|
115
|
+
} catch (_) {
|
|
116
|
+
// Best-effort server-side logout
|
|
117
|
+
}
|
|
118
|
+
}
|
|
112
119
|
dispatch({ type: DauthTypes.SET_IS_LOADING, payload: { isLoading: true } });
|
|
113
120
|
dispatch({
|
|
114
121
|
type: DauthTypes.LOGIN,
|
|
115
122
|
payload: {
|
|
116
123
|
user: {
|
|
117
|
-
language:
|
|
124
|
+
language:
|
|
125
|
+
window.document.documentElement.getAttribute('lang') || 'es',
|
|
118
126
|
},
|
|
119
127
|
domain: {},
|
|
120
128
|
isAuthenticated: false,
|
|
121
129
|
},
|
|
122
130
|
});
|
|
123
131
|
localStorage.removeItem(TOKEN_LS);
|
|
132
|
+
localStorage.removeItem(REFRESH_TOKEN_LS);
|
|
124
133
|
return dispatch({
|
|
125
134
|
type: DauthTypes.SET_IS_LOADING,
|
|
126
135
|
payload: { isLoading: false },
|
|
127
136
|
});
|
|
128
137
|
}
|
|
129
138
|
|
|
139
|
+
export async function refreshSessionAction({
|
|
140
|
+
dispatch,
|
|
141
|
+
domainName,
|
|
142
|
+
}: {
|
|
143
|
+
dispatch: React.Dispatch<any>;
|
|
144
|
+
domainName: string;
|
|
145
|
+
}) {
|
|
146
|
+
const storedRefreshToken = localStorage.getItem(REFRESH_TOKEN_LS);
|
|
147
|
+
if (!storedRefreshToken) {
|
|
148
|
+
return resetUser(dispatch);
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
const refreshResult = await refreshTokenAPI(domainName, storedRefreshToken);
|
|
152
|
+
if (refreshResult.response.status === 200) {
|
|
153
|
+
localStorage.setItem(TOKEN_LS, refreshResult.data.accessToken);
|
|
154
|
+
localStorage.setItem(REFRESH_TOKEN_LS, refreshResult.data.refreshToken);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// Refresh failed — revoked or expired
|
|
158
|
+
resetUser(dispatch);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.error(error);
|
|
161
|
+
resetUser(dispatch);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
130
165
|
type TSetUpdateAction = {
|
|
131
166
|
dispatch: React.Dispatch<any>;
|
|
132
167
|
domainName: string;
|
|
@@ -224,40 +259,6 @@ export async function sendEmailVerificationAction({
|
|
|
224
259
|
}
|
|
225
260
|
}
|
|
226
261
|
|
|
227
|
-
export async function checkTokenAction({
|
|
228
|
-
dispatch,
|
|
229
|
-
domainName,
|
|
230
|
-
token,
|
|
231
|
-
}: {
|
|
232
|
-
dispatch: React.Dispatch<any>;
|
|
233
|
-
domainName: string;
|
|
234
|
-
token: string;
|
|
235
|
-
}) {
|
|
236
|
-
try {
|
|
237
|
-
const refreshAccessTokenFetch = await refreshAccessTokenAPI(
|
|
238
|
-
domainName,
|
|
239
|
-
token
|
|
240
|
-
);
|
|
241
|
-
if (refreshAccessTokenFetch.response.status === 200) {
|
|
242
|
-
if (refreshAccessTokenFetch.data.accessToken) {
|
|
243
|
-
localStorage.setItem(
|
|
244
|
-
TOKEN_LS,
|
|
245
|
-
refreshAccessTokenFetch.data.accessToken
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
return;
|
|
249
|
-
} else {
|
|
250
|
-
window.location.replace(
|
|
251
|
-
`${getClientBasePath()}/${domainName}/${routes.signin}`
|
|
252
|
-
);
|
|
253
|
-
return resetUser(dispatch);
|
|
254
|
-
}
|
|
255
|
-
} catch (error) {
|
|
256
|
-
resetUser(dispatch);
|
|
257
|
-
throw error;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
262
|
export async function getAccessTokenAction({
|
|
262
263
|
dispatch,
|
|
263
264
|
domainName,
|
|
@@ -266,28 +267,31 @@ export async function getAccessTokenAction({
|
|
|
266
267
|
domainName: string;
|
|
267
268
|
}) {
|
|
268
269
|
const token_ls = localStorage.getItem(TOKEN_LS);
|
|
269
|
-
if (!token_ls) return;
|
|
270
|
+
if (!token_ls) return 'token-not-found';
|
|
271
|
+
// Decode JWT to check expiry (without verification — that's the server's job)
|
|
270
272
|
try {
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
273
|
+
const payloadB64 = token_ls.split('.')[1];
|
|
274
|
+
if (payloadB64) {
|
|
275
|
+
const payload = JSON.parse(atob(payloadB64));
|
|
276
|
+
const expiresIn = (payload.exp || 0) * 1000 - Date.now();
|
|
277
|
+
// If token expires in less than 5 minutes, refresh proactively
|
|
278
|
+
if (expiresIn < 5 * 60 * 1000) {
|
|
279
|
+
await refreshSessionAction({ dispatch, domainName });
|
|
280
|
+
const refreshedToken = localStorage.getItem(TOKEN_LS);
|
|
281
|
+
return refreshedToken || 'token-not-found';
|
|
282
|
+
}
|
|
280
283
|
}
|
|
281
|
-
} catch (
|
|
282
|
-
|
|
283
|
-
throw error;
|
|
284
|
+
} catch (_) {
|
|
285
|
+
// If decode fails, return stored token and let server validate
|
|
284
286
|
}
|
|
287
|
+
return token_ls;
|
|
285
288
|
}
|
|
286
289
|
|
|
287
290
|
///////////////////////////////////////////
|
|
288
291
|
//////////////////////////////////////////
|
|
289
292
|
export const resetUser = (dispatch: React.Dispatch<any>) => {
|
|
290
293
|
localStorage.removeItem(TOKEN_LS);
|
|
294
|
+
localStorage.removeItem(REFRESH_TOKEN_LS);
|
|
291
295
|
return dispatch({
|
|
292
296
|
type: DauthTypes.LOGIN,
|
|
293
297
|
payload: {
|