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