@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/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) return toUser(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
- if (hydrated) return hydrated;
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 ?? (serverJwt ? decodeJwtPayload(serverJwt) : null);
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,