@netlify/identity 0.3.0-alpha.6 → 0.3.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/README.md +53 -26
- package/dist/index.cjs +122 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -2
- package/dist/index.d.ts +36 -2
- package/dist/index.js +121 -4
- package/dist/index.js.map +1 -1
- package/package.json +10 -3
package/dist/index.js
CHANGED
|
@@ -22,6 +22,7 @@ var AuthError = class _AuthError extends Error {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
static from(error) {
|
|
25
|
+
if (error instanceof _AuthError) return error;
|
|
25
26
|
const message = error instanceof Error ? error.message : String(error);
|
|
26
27
|
return new _AuthError(message, void 0, { cause: error });
|
|
27
28
|
}
|
|
@@ -97,6 +98,7 @@ var getIdentityContext = () => {
|
|
|
97
98
|
var NF_JWT_COOKIE = "nf_jwt";
|
|
98
99
|
var NF_REFRESH_COOKIE = "nf_refresh";
|
|
99
100
|
var getCookie = (name) => {
|
|
101
|
+
if (typeof document === "undefined") return null;
|
|
100
102
|
const match = document.cookie.match(new RegExp(`(?:^|; )${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}=([^;]*)`));
|
|
101
103
|
if (!match) return null;
|
|
102
104
|
try {
|
|
@@ -130,12 +132,14 @@ var deleteAuthCookies = (cookies) => {
|
|
|
130
132
|
cookies.delete(NF_REFRESH_COOKIE);
|
|
131
133
|
};
|
|
132
134
|
var setBrowserAuthCookies = (accessToken, refreshToken) => {
|
|
135
|
+
if (typeof document === "undefined") return;
|
|
133
136
|
document.cookie = `${NF_JWT_COOKIE}=${encodeURIComponent(accessToken)}; path=/; secure; samesite=lax`;
|
|
134
137
|
if (refreshToken) {
|
|
135
138
|
document.cookie = `${NF_REFRESH_COOKIE}=${encodeURIComponent(refreshToken)}; path=/; secure; samesite=lax`;
|
|
136
139
|
}
|
|
137
140
|
};
|
|
138
141
|
var deleteBrowserAuthCookies = () => {
|
|
142
|
+
if (typeof document === "undefined") return;
|
|
139
143
|
document.cookie = `${NF_JWT_COOKIE}=; path=/; secure; samesite=lax; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
|
140
144
|
document.cookie = `${NF_REFRESH_COOKIE}=; path=/; secure; samesite=lax; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
|
141
145
|
};
|
|
@@ -218,6 +222,105 @@ var onAuthChange = (callback) => {
|
|
|
218
222
|
};
|
|
219
223
|
};
|
|
220
224
|
|
|
225
|
+
// src/refresh.ts
|
|
226
|
+
var REFRESH_MARGIN_S = 60;
|
|
227
|
+
var refreshTimer = null;
|
|
228
|
+
var startTokenRefresh = () => {
|
|
229
|
+
if (!isBrowser()) return;
|
|
230
|
+
stopTokenRefresh();
|
|
231
|
+
const client = getGoTrueClient();
|
|
232
|
+
const user = client?.currentUser();
|
|
233
|
+
if (!user) return;
|
|
234
|
+
const token = user.tokenDetails();
|
|
235
|
+
if (!token?.expires_at) return;
|
|
236
|
+
const nowS = Math.floor(Date.now() / 1e3);
|
|
237
|
+
const expiresAtS = typeof token.expires_at === "number" && token.expires_at > 1e12 ? Math.floor(token.expires_at / 1e3) : token.expires_at;
|
|
238
|
+
const delayMs = Math.max(0, expiresAtS - nowS - REFRESH_MARGIN_S) * 1e3;
|
|
239
|
+
refreshTimer = setTimeout(async () => {
|
|
240
|
+
try {
|
|
241
|
+
const freshJwt = await user.jwt(true);
|
|
242
|
+
const freshDetails = user.tokenDetails();
|
|
243
|
+
setBrowserAuthCookies(freshJwt, freshDetails?.refresh_token);
|
|
244
|
+
emitAuthEvent(AUTH_EVENTS.TOKEN_REFRESH, toUser(user));
|
|
245
|
+
startTokenRefresh();
|
|
246
|
+
} catch {
|
|
247
|
+
stopTokenRefresh();
|
|
248
|
+
}
|
|
249
|
+
}, delayMs);
|
|
250
|
+
};
|
|
251
|
+
var stopTokenRefresh = () => {
|
|
252
|
+
if (refreshTimer !== null) {
|
|
253
|
+
clearTimeout(refreshTimer);
|
|
254
|
+
refreshTimer = null;
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
var refreshSession = async () => {
|
|
258
|
+
if (isBrowser()) {
|
|
259
|
+
const client = getGoTrueClient();
|
|
260
|
+
const user = client?.currentUser();
|
|
261
|
+
if (!user) return null;
|
|
262
|
+
const details = user.tokenDetails();
|
|
263
|
+
if (details?.expires_at) {
|
|
264
|
+
const nowS2 = Math.floor(Date.now() / 1e3);
|
|
265
|
+
const expiresAtS = typeof details.expires_at === "number" && details.expires_at > 1e12 ? Math.floor(details.expires_at / 1e3) : details.expires_at;
|
|
266
|
+
if (expiresAtS - nowS2 > REFRESH_MARGIN_S) {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
const jwt = await user.jwt(true);
|
|
272
|
+
setBrowserAuthCookies(jwt, user.tokenDetails()?.refresh_token);
|
|
273
|
+
emitAuthEvent(AUTH_EVENTS.TOKEN_REFRESH, toUser(user));
|
|
274
|
+
startTokenRefresh();
|
|
275
|
+
return jwt;
|
|
276
|
+
} catch {
|
|
277
|
+
stopTokenRefresh();
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
const accessToken = getServerCookie(NF_JWT_COOKIE);
|
|
282
|
+
const refreshToken = getServerCookie(NF_REFRESH_COOKIE);
|
|
283
|
+
if (!accessToken || !refreshToken) return null;
|
|
284
|
+
const decoded = decodeJwtPayload(accessToken);
|
|
285
|
+
if (!decoded?.exp) return null;
|
|
286
|
+
const nowS = Math.floor(Date.now() / 1e3);
|
|
287
|
+
if (decoded.exp - nowS > REFRESH_MARGIN_S) {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
const ctx = getIdentityContext();
|
|
291
|
+
const identityUrl = ctx?.url ?? (globalThis.Netlify?.context?.url ? new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href : null);
|
|
292
|
+
if (!identityUrl) {
|
|
293
|
+
throw new AuthError("Could not determine the Identity endpoint URL for token refresh");
|
|
294
|
+
}
|
|
295
|
+
let res;
|
|
296
|
+
try {
|
|
297
|
+
res = await fetch(`${identityUrl}/token`, {
|
|
298
|
+
method: "POST",
|
|
299
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
300
|
+
body: new URLSearchParams({ grant_type: "refresh_token", refresh_token: refreshToken }).toString()
|
|
301
|
+
});
|
|
302
|
+
} catch (error) {
|
|
303
|
+
throw AuthError.from(error);
|
|
304
|
+
}
|
|
305
|
+
if (!res.ok) {
|
|
306
|
+
const errorBody = await res.json().catch(() => ({}));
|
|
307
|
+
if (res.status === 401 || res.status === 400) {
|
|
308
|
+
const cookies2 = globalThis.Netlify?.context?.cookies;
|
|
309
|
+
if (cookies2) {
|
|
310
|
+
deleteAuthCookies(cookies2);
|
|
311
|
+
}
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
throw new AuthError(errorBody.msg || `Token refresh failed (${res.status})`, res.status);
|
|
315
|
+
}
|
|
316
|
+
const data = await res.json();
|
|
317
|
+
const cookies = globalThis.Netlify?.context?.cookies;
|
|
318
|
+
if (cookies) {
|
|
319
|
+
setAuthCookies(cookies, data.access_token, data.refresh_token);
|
|
320
|
+
}
|
|
321
|
+
return data.access_token;
|
|
322
|
+
};
|
|
323
|
+
|
|
221
324
|
// src/auth.ts
|
|
222
325
|
var getCookies = () => {
|
|
223
326
|
const cookies = globalThis.Netlify?.context?.cookies;
|
|
@@ -282,6 +385,7 @@ var login = async (email, password) => {
|
|
|
282
385
|
const jwt = await gotrueUser.jwt();
|
|
283
386
|
setBrowserAuthCookies(jwt, gotrueUser.tokenDetails()?.refresh_token);
|
|
284
387
|
const user = toUser(gotrueUser);
|
|
388
|
+
startTokenRefresh();
|
|
285
389
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
286
390
|
return user;
|
|
287
391
|
} catch (error) {
|
|
@@ -326,6 +430,7 @@ var signup = async (email, password, data) => {
|
|
|
326
430
|
const refreshToken = response.tokenDetails?.()?.refresh_token;
|
|
327
431
|
setBrowserAuthCookies(jwt, refreshToken);
|
|
328
432
|
}
|
|
433
|
+
startTokenRefresh();
|
|
329
434
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
330
435
|
}
|
|
331
436
|
return user;
|
|
@@ -357,6 +462,7 @@ var logout = async () => {
|
|
|
357
462
|
await currentUser.logout();
|
|
358
463
|
}
|
|
359
464
|
deleteBrowserAuthCookies();
|
|
465
|
+
stopTokenRefresh();
|
|
360
466
|
emitAuthEvent(AUTH_EVENTS.LOGOUT, null);
|
|
361
467
|
} catch (error) {
|
|
362
468
|
throw AuthError.from(error);
|
|
@@ -409,6 +515,7 @@ var handleOAuthCallback = async (client, params, accessToken) => {
|
|
|
409
515
|
);
|
|
410
516
|
setBrowserAuthCookies(accessToken, refreshToken || void 0);
|
|
411
517
|
const user = toUser(gotrueUser);
|
|
518
|
+
startTokenRefresh();
|
|
412
519
|
clearHash();
|
|
413
520
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
414
521
|
return { type: "oauth", user };
|
|
@@ -418,6 +525,7 @@ var handleConfirmationCallback = async (client, token) => {
|
|
|
418
525
|
const jwt = await gotrueUser.jwt();
|
|
419
526
|
setBrowserAuthCookies(jwt, gotrueUser.tokenDetails()?.refresh_token);
|
|
420
527
|
const user = toUser(gotrueUser);
|
|
528
|
+
startTokenRefresh();
|
|
421
529
|
clearHash();
|
|
422
530
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
423
531
|
return { type: "confirmation", user };
|
|
@@ -427,6 +535,7 @@ var handleRecoveryCallback = async (client, token) => {
|
|
|
427
535
|
const jwt = await gotrueUser.jwt();
|
|
428
536
|
setBrowserAuthCookies(jwt, gotrueUser.tokenDetails()?.refresh_token);
|
|
429
537
|
const user = toUser(gotrueUser);
|
|
538
|
+
startTokenRefresh();
|
|
430
539
|
clearHash();
|
|
431
540
|
emitAuthEvent(AUTH_EVENTS.RECOVERY, user);
|
|
432
541
|
return { type: "recovery", user };
|
|
@@ -470,7 +579,10 @@ var hydrateSession = async () => {
|
|
|
470
579
|
if (!isBrowser()) return null;
|
|
471
580
|
const client = getClient();
|
|
472
581
|
const currentUser = client.currentUser();
|
|
473
|
-
if (currentUser)
|
|
582
|
+
if (currentUser) {
|
|
583
|
+
startTokenRefresh();
|
|
584
|
+
return toUser(currentUser);
|
|
585
|
+
}
|
|
474
586
|
const accessToken = getCookie(NF_JWT_COOKIE);
|
|
475
587
|
if (!accessToken) return null;
|
|
476
588
|
const refreshToken = getCookie(NF_REFRESH_COOKIE) ?? "";
|
|
@@ -494,6 +606,7 @@ var hydrateSession = async () => {
|
|
|
494
606
|
return null;
|
|
495
607
|
}
|
|
496
608
|
const user = toUser(gotrueUser);
|
|
609
|
+
startTokenRefresh();
|
|
497
610
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
498
611
|
return user;
|
|
499
612
|
};
|
|
@@ -588,6 +701,7 @@ var getUser = async () => {
|
|
|
588
701
|
}
|
|
589
702
|
return null;
|
|
590
703
|
}
|
|
704
|
+
startTokenRefresh();
|
|
591
705
|
return toUser(currentUser);
|
|
592
706
|
}
|
|
593
707
|
const jwt = getCookie(NF_JWT_COOKIE);
|
|
@@ -595,8 +709,7 @@ var getUser = async () => {
|
|
|
595
709
|
const claims2 = decodeJwtPayload(jwt);
|
|
596
710
|
if (!claims2) return null;
|
|
597
711
|
const hydrated = await hydrateSession();
|
|
598
|
-
|
|
599
|
-
return claimsToUser(claims2);
|
|
712
|
+
return hydrated ?? null;
|
|
600
713
|
}
|
|
601
714
|
triggerNextjsDynamic();
|
|
602
715
|
const identityContext = globalThis.netlifyIdentityContext;
|
|
@@ -608,7 +721,7 @@ var getUser = async () => {
|
|
|
608
721
|
if (fullUser) return fullUser;
|
|
609
722
|
}
|
|
610
723
|
}
|
|
611
|
-
const claims = identityContext?.user ??
|
|
724
|
+
const claims = identityContext?.user ?? null;
|
|
612
725
|
return claims ? claimsToUser(claims) : null;
|
|
613
726
|
};
|
|
614
727
|
var isAuthenticated = async () => await getUser() !== null;
|
|
@@ -671,6 +784,7 @@ var recoverPassword = async (token, newPassword) => {
|
|
|
671
784
|
const gotrueUser = await client.recover(token, persistSession);
|
|
672
785
|
const updatedUser = await gotrueUser.update({ password: newPassword });
|
|
673
786
|
const user = toUser(updatedUser);
|
|
787
|
+
startTokenRefresh();
|
|
674
788
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
675
789
|
return user;
|
|
676
790
|
} catch (error) {
|
|
@@ -682,6 +796,7 @@ var confirmEmail = async (token) => {
|
|
|
682
796
|
try {
|
|
683
797
|
const gotrueUser = await client.confirm(token, persistSession);
|
|
684
798
|
const user = toUser(gotrueUser);
|
|
799
|
+
startTokenRefresh();
|
|
685
800
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
686
801
|
return user;
|
|
687
802
|
} catch (error) {
|
|
@@ -693,6 +808,7 @@ var acceptInvite = async (token, password) => {
|
|
|
693
808
|
try {
|
|
694
809
|
const gotrueUser = await client.acceptInvite(token, password, persistSession);
|
|
695
810
|
const user = toUser(gotrueUser);
|
|
811
|
+
startTokenRefresh();
|
|
696
812
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
697
813
|
return user;
|
|
698
814
|
} catch (error) {
|
|
@@ -889,6 +1005,7 @@ export {
|
|
|
889
1005
|
oauthLogin,
|
|
890
1006
|
onAuthChange,
|
|
891
1007
|
recoverPassword,
|
|
1008
|
+
refreshSession,
|
|
892
1009
|
requestPasswordRecovery,
|
|
893
1010
|
signup,
|
|
894
1011
|
updateUser,
|