@netlify/identity 0.3.0-alpha.7 → 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 +118 -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 +117 -4
- package/dist/index.js.map +1 -1
- package/package.json +10 -3
package/dist/index.js
CHANGED
|
@@ -222,6 +222,105 @@ var onAuthChange = (callback) => {
|
|
|
222
222
|
};
|
|
223
223
|
};
|
|
224
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
|
+
|
|
225
324
|
// src/auth.ts
|
|
226
325
|
var getCookies = () => {
|
|
227
326
|
const cookies = globalThis.Netlify?.context?.cookies;
|
|
@@ -286,6 +385,7 @@ var login = async (email, password) => {
|
|
|
286
385
|
const jwt = await gotrueUser.jwt();
|
|
287
386
|
setBrowserAuthCookies(jwt, gotrueUser.tokenDetails()?.refresh_token);
|
|
288
387
|
const user = toUser(gotrueUser);
|
|
388
|
+
startTokenRefresh();
|
|
289
389
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
290
390
|
return user;
|
|
291
391
|
} catch (error) {
|
|
@@ -330,6 +430,7 @@ var signup = async (email, password, data) => {
|
|
|
330
430
|
const refreshToken = response.tokenDetails?.()?.refresh_token;
|
|
331
431
|
setBrowserAuthCookies(jwt, refreshToken);
|
|
332
432
|
}
|
|
433
|
+
startTokenRefresh();
|
|
333
434
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
334
435
|
}
|
|
335
436
|
return user;
|
|
@@ -361,6 +462,7 @@ var logout = async () => {
|
|
|
361
462
|
await currentUser.logout();
|
|
362
463
|
}
|
|
363
464
|
deleteBrowserAuthCookies();
|
|
465
|
+
stopTokenRefresh();
|
|
364
466
|
emitAuthEvent(AUTH_EVENTS.LOGOUT, null);
|
|
365
467
|
} catch (error) {
|
|
366
468
|
throw AuthError.from(error);
|
|
@@ -413,6 +515,7 @@ var handleOAuthCallback = async (client, params, accessToken) => {
|
|
|
413
515
|
);
|
|
414
516
|
setBrowserAuthCookies(accessToken, refreshToken || void 0);
|
|
415
517
|
const user = toUser(gotrueUser);
|
|
518
|
+
startTokenRefresh();
|
|
416
519
|
clearHash();
|
|
417
520
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
418
521
|
return { type: "oauth", user };
|
|
@@ -422,6 +525,7 @@ var handleConfirmationCallback = async (client, token) => {
|
|
|
422
525
|
const jwt = await gotrueUser.jwt();
|
|
423
526
|
setBrowserAuthCookies(jwt, gotrueUser.tokenDetails()?.refresh_token);
|
|
424
527
|
const user = toUser(gotrueUser);
|
|
528
|
+
startTokenRefresh();
|
|
425
529
|
clearHash();
|
|
426
530
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
427
531
|
return { type: "confirmation", user };
|
|
@@ -431,6 +535,7 @@ var handleRecoveryCallback = async (client, token) => {
|
|
|
431
535
|
const jwt = await gotrueUser.jwt();
|
|
432
536
|
setBrowserAuthCookies(jwt, gotrueUser.tokenDetails()?.refresh_token);
|
|
433
537
|
const user = toUser(gotrueUser);
|
|
538
|
+
startTokenRefresh();
|
|
434
539
|
clearHash();
|
|
435
540
|
emitAuthEvent(AUTH_EVENTS.RECOVERY, user);
|
|
436
541
|
return { type: "recovery", user };
|
|
@@ -474,7 +579,10 @@ var hydrateSession = async () => {
|
|
|
474
579
|
if (!isBrowser()) return null;
|
|
475
580
|
const client = getClient();
|
|
476
581
|
const currentUser = client.currentUser();
|
|
477
|
-
if (currentUser)
|
|
582
|
+
if (currentUser) {
|
|
583
|
+
startTokenRefresh();
|
|
584
|
+
return toUser(currentUser);
|
|
585
|
+
}
|
|
478
586
|
const accessToken = getCookie(NF_JWT_COOKIE);
|
|
479
587
|
if (!accessToken) return null;
|
|
480
588
|
const refreshToken = getCookie(NF_REFRESH_COOKIE) ?? "";
|
|
@@ -498,6 +606,7 @@ var hydrateSession = async () => {
|
|
|
498
606
|
return null;
|
|
499
607
|
}
|
|
500
608
|
const user = toUser(gotrueUser);
|
|
609
|
+
startTokenRefresh();
|
|
501
610
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
502
611
|
return user;
|
|
503
612
|
};
|
|
@@ -592,6 +701,7 @@ var getUser = async () => {
|
|
|
592
701
|
}
|
|
593
702
|
return null;
|
|
594
703
|
}
|
|
704
|
+
startTokenRefresh();
|
|
595
705
|
return toUser(currentUser);
|
|
596
706
|
}
|
|
597
707
|
const jwt = getCookie(NF_JWT_COOKIE);
|
|
@@ -599,8 +709,7 @@ var getUser = async () => {
|
|
|
599
709
|
const claims2 = decodeJwtPayload(jwt);
|
|
600
710
|
if (!claims2) return null;
|
|
601
711
|
const hydrated = await hydrateSession();
|
|
602
|
-
|
|
603
|
-
return claimsToUser(claims2);
|
|
712
|
+
return hydrated ?? null;
|
|
604
713
|
}
|
|
605
714
|
triggerNextjsDynamic();
|
|
606
715
|
const identityContext = globalThis.netlifyIdentityContext;
|
|
@@ -612,7 +721,7 @@ var getUser = async () => {
|
|
|
612
721
|
if (fullUser) return fullUser;
|
|
613
722
|
}
|
|
614
723
|
}
|
|
615
|
-
const claims = identityContext?.user ??
|
|
724
|
+
const claims = identityContext?.user ?? null;
|
|
616
725
|
return claims ? claimsToUser(claims) : null;
|
|
617
726
|
};
|
|
618
727
|
var isAuthenticated = async () => await getUser() !== null;
|
|
@@ -675,6 +784,7 @@ var recoverPassword = async (token, newPassword) => {
|
|
|
675
784
|
const gotrueUser = await client.recover(token, persistSession);
|
|
676
785
|
const updatedUser = await gotrueUser.update({ password: newPassword });
|
|
677
786
|
const user = toUser(updatedUser);
|
|
787
|
+
startTokenRefresh();
|
|
678
788
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
679
789
|
return user;
|
|
680
790
|
} catch (error) {
|
|
@@ -686,6 +796,7 @@ var confirmEmail = async (token) => {
|
|
|
686
796
|
try {
|
|
687
797
|
const gotrueUser = await client.confirm(token, persistSession);
|
|
688
798
|
const user = toUser(gotrueUser);
|
|
799
|
+
startTokenRefresh();
|
|
689
800
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
690
801
|
return user;
|
|
691
802
|
} catch (error) {
|
|
@@ -697,6 +808,7 @@ var acceptInvite = async (token, password) => {
|
|
|
697
808
|
try {
|
|
698
809
|
const gotrueUser = await client.acceptInvite(token, password, persistSession);
|
|
699
810
|
const user = toUser(gotrueUser);
|
|
811
|
+
startTokenRefresh();
|
|
700
812
|
emitAuthEvent(AUTH_EVENTS.LOGIN, user);
|
|
701
813
|
return user;
|
|
702
814
|
} catch (error) {
|
|
@@ -893,6 +1005,7 @@ export {
|
|
|
893
1005
|
oauthLogin,
|
|
894
1006
|
onAuthChange,
|
|
895
1007
|
recoverPassword,
|
|
1008
|
+
refreshSession,
|
|
896
1009
|
requestPasswordRecovery,
|
|
897
1010
|
signup,
|
|
898
1011
|
updateUser,
|