@workos-inc/authkit-nextjs 2.4.1 → 2.4.3

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 CHANGED
@@ -47,16 +47,21 @@ To use the `signOut` method, you'll need to set a default Logout URI in your Wor
47
47
 
48
48
  Certain environment variables are optional and can be used to debug or configure cookie settings.
49
49
 
50
+ | Environment Variable | Default Value | Description |
51
+ |---------------------|---------------|-------------|
52
+ | `WORKOS_COOKIE_MAX_AGE` | `34560000` (400 days) | Maximum age of the cookie in seconds |
53
+ | `WORKOS_COOKIE_DOMAIN` | None | Domain for the cookie. When empty, the cookie is only valid for the current domain |
54
+ | `WORKOS_COOKIE_NAME` | `'wos-session'` | Name of the session cookie |
55
+ | `WORKOS_API_HOSTNAME` | `'api.workos.com'` | Base WorkOS API URL |
56
+ | `WORKOS_API_HTTPS` | `true` | Whether to use HTTPS in API calls |
57
+ | `WORKOS_API_PORT` | None | Port to use for API calls. When not set, uses standard ports (443 for HTTPS, 80 for HTTP) |
58
+ | `WORKOS_COOKIE_SAMESITE` | `'lax'` | SameSite attribute for cookies. Options: `'lax'`, `'strict'`, or `'none'` |
59
+
60
+ Example usage:
50
61
  ```sh
51
- WORKOS_COOKIE_MAX_AGE='600' # maximum age of the cookie in seconds. Defaults to 400 days, the maximum allowed in Chrome
62
+ WORKOS_COOKIE_MAX_AGE='600'
52
63
  WORKOS_COOKIE_DOMAIN='example.com'
53
- WORKOS_COOKIE_NAME='authkit-cookie'
54
- WORKOS_API_HOSTNAME='api.workos.com' # base WorkOS API URL
55
- WORKOS_API_HTTPS=true # whether to use HTTPS in API calls
56
- WORKOS_API_PORT=3000 # port to use for API calls
57
-
58
- # Only change this if you specifically need cross-origin cookie support.
59
- WORKOS_COOKIE_SAMESITE='lax' # SameSite attribute for cookies: 'lax' (default), 'strict', or 'none'.
64
+ WORKOS_COOKIE_NAME='my-auth-cookie'
60
65
  ```
61
66
 
62
67
  > [!WARNING]
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import React, { createContext, useContext, useEffect, useState } from 'react';
2
+ import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
3
3
  import { checkSessionAction, getAuthAction, handleSignOutAction, refreshAuthAction, switchToOrganizationAction, } from '../actions.js';
4
4
  const AuthContext = createContext(undefined);
5
5
  export const AuthKitProvider = ({ children, onSessionExpired }) => {
@@ -12,7 +12,7 @@ export const AuthKitProvider = ({ children, onSessionExpired }) => {
12
12
  const [featureFlags, setFeatureFlags] = useState(undefined);
13
13
  const [impersonator, setImpersonator] = useState(undefined);
14
14
  const [loading, setLoading] = useState(true);
15
- const getAuth = async ({ ensureSignedIn = false } = {}) => {
15
+ const getAuth = useCallback(async ({ ensureSignedIn = false } = {}) => {
16
16
  setLoading(true);
17
17
  try {
18
18
  const auth = await getAuthAction({ ensureSignedIn });
@@ -38,8 +38,8 @@ export const AuthKitProvider = ({ children, onSessionExpired }) => {
38
38
  finally {
39
39
  setLoading(false);
40
40
  }
41
- };
42
- const switchToOrganization = async (organizationId, options = {}) => {
41
+ }, []);
42
+ const switchToOrganization = useCallback(async (organizationId, options = {}) => {
43
43
  const opts = { revalidationStrategy: 'none', ...options };
44
44
  const result = await switchToOrganizationAction(organizationId, {
45
45
  revalidationStrategy: 'none',
@@ -49,8 +49,8 @@ export const AuthKitProvider = ({ children, onSessionExpired }) => {
49
49
  await getAuth({ ensureSignedIn: true });
50
50
  }
51
51
  return result;
52
- };
53
- const refreshAuth = async ({ ensureSignedIn = false, organizationId, } = {}) => {
52
+ }, []);
53
+ const refreshAuth = useCallback(async ({ ensureSignedIn = false, organizationId } = {}) => {
54
54
  try {
55
55
  setLoading(true);
56
56
  const auth = await refreshAuthAction({ ensureSignedIn, organizationId });
@@ -69,10 +69,10 @@ export const AuthKitProvider = ({ children, onSessionExpired }) => {
69
69
  finally {
70
70
  setLoading(false);
71
71
  }
72
- };
73
- const signOut = async ({ returnTo } = {}) => {
72
+ }, []);
73
+ const signOut = useCallback(async ({ returnTo } = {}) => {
74
74
  await handleSignOutAction({ returnTo });
75
- };
75
+ }, []);
76
76
  useEffect(() => {
77
77
  getAuth();
78
78
  // Return early if the session expired checks are disabled.
@@ -1 +1 @@
1
- {"version":3,"file":"authkit-provider.js","sourceRoot":"","sources":["../../../src/components/authkit-provider.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authkit-provider.js","sourceRoot":"","sources":["../../../src/components/authkit-provider.tsx"],"names":[],"mappings":"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"}
@@ -1,8 +1,10 @@
1
1
  import { useCallback, useEffect, useReducer, useRef } from 'react';
2
2
  import { getAccessTokenAction, refreshAccessTokenAction } from '../actions.js';
3
3
  import { useAuth } from './authkit-provider.js';
4
+ import { decodeJwt } from '../jwt.js';
4
5
  const TOKEN_EXPIRY_BUFFER_SECONDS = 60;
5
6
  const MIN_REFRESH_DELAY_SECONDS = 15; // minimum delay before refreshing token
7
+ const MAX_REFRESH_DELAY_SECONDS = 24 * 60 * 60; // 24 hours
6
8
  const RETRY_DELAY_SECONDS = 300; // 5 minutes
7
9
  function tokenReducer(state, action) {
8
10
  switch (action.type) {
@@ -20,20 +22,21 @@ function tokenReducer(state, action) {
20
22
  }
21
23
  }
22
24
  function getRefreshDelay(timeUntilExpiry) {
23
- return Math.max((timeUntilExpiry - TOKEN_EXPIRY_BUFFER_SECONDS) * 1000, MIN_REFRESH_DELAY_SECONDS * 1000);
25
+ const idealDelay = (timeUntilExpiry - TOKEN_EXPIRY_BUFFER_SECONDS) * 1000;
26
+ return Math.min(Math.max(idealDelay, MIN_REFRESH_DELAY_SECONDS * 1000), MAX_REFRESH_DELAY_SECONDS * 1000);
24
27
  }
25
- function parseToken(token) {
28
+ function parseTokenPayload(token) {
26
29
  // istanbul ignore next
27
30
  if (!token) {
28
31
  return null;
29
32
  }
30
33
  try {
31
- const parts = token.split('.');
32
- if (parts.length !== 3) {
34
+ const { payload } = decodeJwt(token);
35
+ const now = Math.floor(Date.now() / 1000);
36
+ // istanbul ignore next - if the token does not have an exp claim, we cannot determine expiry
37
+ if (typeof payload.exp !== 'number') {
33
38
  return null;
34
39
  }
35
- const payload = JSON.parse(atob(parts[1]));
36
- const now = Math.floor(Date.now() / 1000);
37
40
  return {
38
41
  payload,
39
42
  expiresAt: payload.exp,
@@ -66,6 +69,7 @@ export function useAccessToken() {
66
69
  }
67
70
  }, []);
68
71
  const updateToken = useCallback(async () => {
72
+ // istanbul ignore next - safety guard against concurrent fetches
69
73
  if (fetchingRef.current) {
70
74
  return;
71
75
  }
@@ -74,14 +78,14 @@ export function useAccessToken() {
74
78
  try {
75
79
  let token = await getAccessTokenAction();
76
80
  if (token) {
77
- const tokenData = parseToken(token);
81
+ const tokenData = parseTokenPayload(token);
78
82
  if (!tokenData || tokenData.isExpiring) {
79
83
  token = await refreshAccessTokenAction();
80
84
  }
81
85
  }
82
86
  dispatch({ type: 'FETCH_SUCCESS', token });
83
87
  if (token) {
84
- const tokenData = parseToken(token);
88
+ const tokenData = parseTokenPayload(token);
85
89
  if (tokenData) {
86
90
  const delay = getRefreshDelay(tokenData.timeUntilExpiry);
87
91
  clearRefreshTimeout();
@@ -92,6 +96,7 @@ export function useAccessToken() {
92
96
  }
93
97
  catch (error) {
94
98
  dispatch({ type: 'FETCH_ERROR', error: error instanceof Error ? error : new Error(String(error)) });
99
+ clearRefreshTimeout();
95
100
  refreshTimeoutRef.current = setTimeout(updateToken, RETRY_DELAY_SECONDS * 1000);
96
101
  }
97
102
  finally {
@@ -109,7 +114,7 @@ export function useAccessToken() {
109
114
  const token = await getAccessTokenAction();
110
115
  dispatch({ type: 'FETCH_SUCCESS', token });
111
116
  if (token) {
112
- const tokenData = parseToken(token);
117
+ const tokenData = parseTokenPayload(token);
113
118
  if (tokenData) {
114
119
  const delay = getRefreshDelay(tokenData.timeUntilExpiry);
115
120
  clearRefreshTimeout();
@@ -121,6 +126,7 @@ export function useAccessToken() {
121
126
  catch (error) {
122
127
  const typedError = error instanceof Error ? error : new Error(String(error));
123
128
  dispatch({ type: 'FETCH_ERROR', error: typedError });
129
+ clearRefreshTimeout();
124
130
  refreshTimeoutRef.current = setTimeout(updateToken, RETRY_DELAY_SECONDS * 1000);
125
131
  }
126
132
  finally {
@@ -1 +1 @@
1
- {"version":3,"file":"useAccessToken.js","sourceRoot":"","sources":["../../../src/components/useAccessToken.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useAccessToken.js","sourceRoot":"","sources":["../../../src/components/useAccessToken.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { useMemo } from 'react';
2
2
  import { useAccessToken } from './useAccessToken.js';
3
- import { decodeJwt } from 'jose';
3
+ import { decodeJwt } from '../jwt.js';
4
4
  /**
5
5
  * A hook that retrieves the claims from the access token.
6
6
  *
@@ -17,7 +17,7 @@ export function useTokenClaims() {
17
17
  return {};
18
18
  }
19
19
  try {
20
- return decodeJwt(accessToken);
20
+ return decodeJwt(accessToken).payload;
21
21
  }
22
22
  catch (_a) {
23
23
  return {};
@@ -1 +1 @@
1
- {"version":3,"file":"useTokenClaims.js","sourceRoot":"","sources":["../../../src/components/useTokenClaims.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAmB,MAAM,MAAM,CAAC;AAIlD;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,EAAE,WAAW,EAAE,GAAG,cAAc,EAAE,CAAC;IAEzC,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,CAAC;YACH,OAAO,SAAS,CAAI,WAAW,CAAC,CAAC;QACnC,CAAC;QAAC,WAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;AACpB,CAAC"}
1
+ {"version":3,"file":"useTokenClaims.js","sourceRoot":"","sources":["../../../src/components/useTokenClaims.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAoB,MAAM,WAAW,CAAC;AAExD;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,EAAE,WAAW,EAAE,GAAG,cAAc,EAAE,CAAC;IAEzC,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,CAAC;YACH,OAAO,SAAS,CAAI,WAAW,CAAC,CAAC,OAAO,CAAC;QAC3C,CAAC;QAAC,WAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Decodes a base64url encoded string
3
+ * @param input The base64url string to decode
4
+ * @returns The decoded string
5
+ */
6
+ function decodeBase64Url(input) {
7
+ const base64 = input.replace(/-/g, '+').replace(/_/g, '/');
8
+ const padding = '='.repeat((4 - (base64.length % 4)) % 4);
9
+ return atob(base64 + padding);
10
+ }
11
+ /**
12
+ * Decodes a JWT token and returns its header and payload
13
+ * @param token The JWT token to decode
14
+ * @return An object containing the decoded header and payload
15
+ * @throws Error if the token is not in a valid JWT format or if decoding fails
16
+ */
17
+ // should replace this with jose if we ever need to verify the JWT
18
+ export function decodeJwt(token) {
19
+ const parts = token.split('.');
20
+ if (parts.length !== 3) {
21
+ throw new Error('Invalid JWT format');
22
+ }
23
+ try {
24
+ const header = JSON.parse(decodeBase64Url(parts[0]));
25
+ const payload = JSON.parse(decodeBase64Url(parts[1]));
26
+ return { header, payload };
27
+ }
28
+ catch (error) {
29
+ throw new Error(`Failed to decode JWT: ${error instanceof Error ? error.message : String(error)}`);
30
+ }
31
+ }
32
+ //# sourceMappingURL=jwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/jwt.ts"],"names":[],"mappings":"AAmEA;;;;GAIG;AACH,SAAS,eAAe,CAAC,KAAa;IACpC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC;AAChC,CAAC;AAED;;;;;GAKG;AACH,kEAAkE;AAClE,MAAM,UAAU,SAAS,CACvB,KAAa;IAKb,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAc,CAAC;QAClE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAmB,CAAC;QAExE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,yBAAyB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrG,CAAC;AACH,CAAC"}
@@ -1,5 +1,4 @@
1
- import { type JWTPayload } from 'jose';
2
- type TokenClaims<T> = Partial<JWTPayload & T>;
1
+ import { type TokenClaims } from '../jwt.js';
3
2
  /**
4
3
  * A hook that retrieves the claims from the access token.
5
4
  *
@@ -10,4 +9,3 @@ type TokenClaims<T> = Partial<JWTPayload & T>;
10
9
  * @returns The claims from the access token, or an empty object if the token is not available or cannot be parsed.
11
10
  */
12
11
  export declare function useTokenClaims<T = Record<string, unknown>>(): TokenClaims<T>;
13
- export {};
@@ -0,0 +1,71 @@
1
+ /**
2
+ * JWT (JSON Web Token) Interface Definitions
3
+ */
4
+ export interface JWTHeader {
5
+ 'alg': string;
6
+ 'typ'?: string | undefined;
7
+ 'cty'?: string | undefined;
8
+ 'crit'?: Array<string | Exclude<keyof JWTHeader, 'crit'>> | undefined;
9
+ 'kid'?: string | undefined;
10
+ 'jku'?: string | undefined;
11
+ 'x5u'?: string | string[] | undefined;
12
+ 'x5t#S256'?: string | undefined;
13
+ 'x5t'?: string | undefined;
14
+ 'x5c'?: string | string[] | undefined;
15
+ }
16
+ /**
17
+ * JWT Payload Interface
18
+ */
19
+ export interface JWTPayload {
20
+ /**
21
+ * Session ID of the JWT, used to identify the session
22
+ */
23
+ sid: string;
24
+ /**
25
+ * Issuer of the JWT
26
+ */
27
+ iss: string;
28
+ /**
29
+ * Subject of the JWT
30
+ */
31
+ sub: string;
32
+ /**
33
+ * Audience of the JWT, can be a single string or an array of strings
34
+ */
35
+ aud?: string | string[];
36
+ /**
37
+ * Expiration time of the JWT, represented as a Unix timestamp
38
+ */
39
+ exp: number;
40
+ /**
41
+ * Issued at time of the JWT, represented as a Unix timestamp
42
+ */
43
+ iat: number;
44
+ /**
45
+ * JWT ID, a unique identifier for the JWT
46
+ */
47
+ jti: string;
48
+ /**
49
+ * Organization ID associated with the JWT
50
+ */
51
+ org_id?: string;
52
+ /**
53
+ * Role of the user associated with the JWT
54
+ */
55
+ role?: string;
56
+ /**
57
+ * Permissions granted to the user associated with the JWT
58
+ */
59
+ permissions?: string[];
60
+ }
61
+ export type TokenClaims<T> = Partial<JWTPayload & T>;
62
+ /**
63
+ * Decodes a JWT token and returns its header and payload
64
+ * @param token The JWT token to decode
65
+ * @return An object containing the decoded header and payload
66
+ * @throws Error if the token is not in a valid JWT format or if decoding fails
67
+ */
68
+ export declare function decodeJwt<T = Record<string, unknown>>(token: string): {
69
+ header: JWTHeader;
70
+ payload: TokenClaims<T>;
71
+ };
@@ -1,5 +1,5 @@
1
1
  import { WorkOS } from '@workos-inc/node';
2
- export declare const VERSION = "2.4.1";
2
+ export declare const VERSION = "2.4.3";
3
3
  /**
4
4
  * Create a WorkOS instance with the provided API key and options.
5
5
  * If an instance already exists, it returns the existing instance.
@@ -1,7 +1,7 @@
1
1
  import { WorkOS } from '@workos-inc/node';
2
2
  import { WORKOS_API_HOSTNAME, WORKOS_API_KEY, WORKOS_API_HTTPS, WORKOS_API_PORT } from './env-variables.js';
3
3
  import { lazy } from './utils.js';
4
- export const VERSION = '2.4.1';
4
+ export const VERSION = '2.4.3';
5
5
  const options = {
6
6
  apiHostname: WORKOS_API_HOSTNAME,
7
7
  https: WORKOS_API_HTTPS ? WORKOS_API_HTTPS === 'true' : true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workos-inc/authkit-nextjs",
3
- "version": "2.4.1",
3
+ "version": "2.4.3",
4
4
  "description": "Authentication and session helpers for using WorkOS & AuthKit with Next.js",
5
5
  "sideEffects": false,
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import React, { createContext, ReactNode, useContext, useEffect, useState } from 'react';
3
+ import React, { createContext, ReactNode, useCallback, useContext, useEffect, useState } from 'react';
4
4
  import {
5
5
  checkSessionAction,
6
6
  getAuthAction,
@@ -52,7 +52,7 @@ export const AuthKitProvider = ({ children, onSessionExpired }: AuthKitProviderP
52
52
  const [impersonator, setImpersonator] = useState<Impersonator | undefined>(undefined);
53
53
  const [loading, setLoading] = useState(true);
54
54
 
55
- const getAuth = async ({ ensureSignedIn = false }: { ensureSignedIn?: boolean } = {}) => {
55
+ const getAuth = useCallback(async ({ ensureSignedIn = false }: { ensureSignedIn?: boolean } = {}) => {
56
56
  setLoading(true);
57
57
  try {
58
58
  const auth = await getAuthAction({ ensureSignedIn });
@@ -76,48 +76,51 @@ export const AuthKitProvider = ({ children, onSessionExpired }: AuthKitProviderP
76
76
  } finally {
77
77
  setLoading(false);
78
78
  }
79
- };
80
-
81
- const switchToOrganization = async (organizationId: string, options: SwitchToOrganizationOptions = {}) => {
82
- const opts = { revalidationStrategy: 'none', ...options };
83
- const result = await switchToOrganizationAction(organizationId, {
84
- revalidationStrategy: 'none',
85
- ...options,
86
- });
87
-
88
- if (opts.revalidationStrategy === 'none') {
89
- await getAuth({ ensureSignedIn: true });
90
- }
91
-
92
- return result;
93
- };
79
+ }, []);
80
+
81
+ const switchToOrganization = useCallback(
82
+ async (organizationId: string, options: SwitchToOrganizationOptions = {}) => {
83
+ const opts = { revalidationStrategy: 'none', ...options };
84
+ const result = await switchToOrganizationAction(organizationId, {
85
+ revalidationStrategy: 'none',
86
+ ...options,
87
+ });
88
+
89
+ if (opts.revalidationStrategy === 'none') {
90
+ await getAuth({ ensureSignedIn: true });
91
+ }
94
92
 
95
- const refreshAuth = async ({
96
- ensureSignedIn = false,
97
- organizationId,
98
- }: { ensureSignedIn?: boolean; organizationId?: string } = {}) => {
99
- try {
100
- setLoading(true);
101
- const auth = await refreshAuthAction({ ensureSignedIn, organizationId });
93
+ return result;
94
+ },
95
+ [],
96
+ );
102
97
 
103
- setUser(auth.user);
104
- setSessionId(auth.sessionId);
105
- setOrganizationId(auth.organizationId);
106
- setRole(auth.role);
107
- setPermissions(auth.permissions);
108
- setEntitlements(auth.entitlements);
109
- setFeatureFlags(auth.featureFlags);
110
- setImpersonator(auth.impersonator);
111
- } catch (error) {
112
- return error instanceof Error ? { error: error.message } : { error: String(error) };
113
- } finally {
114
- setLoading(false);
115
- }
116
- };
98
+ const refreshAuth = useCallback(
99
+ async ({ ensureSignedIn = false, organizationId }: { ensureSignedIn?: boolean; organizationId?: string } = {}) => {
100
+ try {
101
+ setLoading(true);
102
+ const auth = await refreshAuthAction({ ensureSignedIn, organizationId });
103
+
104
+ setUser(auth.user);
105
+ setSessionId(auth.sessionId);
106
+ setOrganizationId(auth.organizationId);
107
+ setRole(auth.role);
108
+ setPermissions(auth.permissions);
109
+ setEntitlements(auth.entitlements);
110
+ setFeatureFlags(auth.featureFlags);
111
+ setImpersonator(auth.impersonator);
112
+ } catch (error) {
113
+ return error instanceof Error ? { error: error.message } : { error: String(error) };
114
+ } finally {
115
+ setLoading(false);
116
+ }
117
+ },
118
+ [],
119
+ );
117
120
 
118
- const signOut = async ({ returnTo }: { returnTo?: string } = {}) => {
121
+ const signOut = useCallback(async ({ returnTo }: { returnTo?: string } = {}) => {
119
122
  await handleSignOutAction({ returnTo });
120
- };
123
+ }, []);
121
124
 
122
125
  useEffect(() => {
123
126
  getAuth();
@@ -1,9 +1,11 @@
1
1
  import { useCallback, useEffect, useReducer, useRef } from 'react';
2
2
  import { getAccessTokenAction, refreshAccessTokenAction } from '../actions.js';
3
3
  import { useAuth } from './authkit-provider.js';
4
+ import { decodeJwt } from '../jwt.js';
4
5
 
5
6
  const TOKEN_EXPIRY_BUFFER_SECONDS = 60;
6
7
  const MIN_REFRESH_DELAY_SECONDS = 15; // minimum delay before refreshing token
8
+ const MAX_REFRESH_DELAY_SECONDS = 24 * 60 * 60; // 24 hours
7
9
  const RETRY_DELAY_SECONDS = 300; // 5 minutes
8
10
 
9
11
  interface TokenState {
@@ -35,24 +37,25 @@ function tokenReducer(state: TokenState, action: TokenAction): TokenState {
35
37
  }
36
38
 
37
39
  function getRefreshDelay(timeUntilExpiry: number) {
38
- return Math.max((timeUntilExpiry - TOKEN_EXPIRY_BUFFER_SECONDS) * 1000, MIN_REFRESH_DELAY_SECONDS * 1000);
40
+ const idealDelay = (timeUntilExpiry - TOKEN_EXPIRY_BUFFER_SECONDS) * 1000;
41
+ return Math.min(Math.max(idealDelay, MIN_REFRESH_DELAY_SECONDS * 1000), MAX_REFRESH_DELAY_SECONDS * 1000);
39
42
  }
40
43
 
41
- function parseToken(token: string | undefined) {
44
+ function parseTokenPayload(token: string | undefined) {
42
45
  // istanbul ignore next
43
46
  if (!token) {
44
47
  return null;
45
48
  }
46
49
 
47
50
  try {
48
- const parts = token.split('.');
49
- if (parts.length !== 3) {
51
+ const { payload } = decodeJwt(token);
52
+ const now = Math.floor(Date.now() / 1000);
53
+
54
+ // istanbul ignore next - if the token does not have an exp claim, we cannot determine expiry
55
+ if (typeof payload.exp !== 'number') {
50
56
  return null;
51
57
  }
52
58
 
53
- const payload = JSON.parse(atob(parts[1]));
54
- const now = Math.floor(Date.now() / 1000);
55
-
56
59
  return {
57
60
  payload,
58
61
  expiresAt: payload.exp,
@@ -88,6 +91,7 @@ export function useAccessToken() {
88
91
  }, []);
89
92
 
90
93
  const updateToken = useCallback(async () => {
94
+ // istanbul ignore next - safety guard against concurrent fetches
91
95
  if (fetchingRef.current) {
92
96
  return;
93
97
  }
@@ -97,7 +101,7 @@ export function useAccessToken() {
97
101
  try {
98
102
  let token = await getAccessTokenAction();
99
103
  if (token) {
100
- const tokenData = parseToken(token);
104
+ const tokenData = parseTokenPayload(token);
101
105
  if (!tokenData || tokenData.isExpiring) {
102
106
  token = await refreshAccessTokenAction();
103
107
  }
@@ -106,7 +110,7 @@ export function useAccessToken() {
106
110
  dispatch({ type: 'FETCH_SUCCESS', token });
107
111
 
108
112
  if (token) {
109
- const tokenData = parseToken(token);
113
+ const tokenData = parseTokenPayload(token);
110
114
  if (tokenData) {
111
115
  const delay = getRefreshDelay(tokenData.timeUntilExpiry);
112
116
  clearRefreshTimeout();
@@ -117,6 +121,7 @@ export function useAccessToken() {
117
121
  return token;
118
122
  } catch (error) {
119
123
  dispatch({ type: 'FETCH_ERROR', error: error instanceof Error ? error : new Error(String(error)) });
124
+ clearRefreshTimeout();
120
125
  refreshTimeoutRef.current = setTimeout(updateToken, RETRY_DELAY_SECONDS * 1000);
121
126
  } finally {
122
127
  fetchingRef.current = false;
@@ -138,7 +143,7 @@ export function useAccessToken() {
138
143
  dispatch({ type: 'FETCH_SUCCESS', token });
139
144
 
140
145
  if (token) {
141
- const tokenData = parseToken(token);
146
+ const tokenData = parseTokenPayload(token);
142
147
  if (tokenData) {
143
148
  const delay = getRefreshDelay(tokenData.timeUntilExpiry);
144
149
  clearRefreshTimeout();
@@ -150,6 +155,7 @@ export function useAccessToken() {
150
155
  } catch (error) {
151
156
  const typedError = error instanceof Error ? error : new Error(String(error));
152
157
  dispatch({ type: 'FETCH_ERROR', error: typedError });
158
+ clearRefreshTimeout();
153
159
  refreshTimeoutRef.current = setTimeout(updateToken, RETRY_DELAY_SECONDS * 1000);
154
160
  } finally {
155
161
  fetchingRef.current = false;
@@ -1,8 +1,6 @@
1
1
  import { useMemo } from 'react';
2
2
  import { useAccessToken } from './useAccessToken.js';
3
- import { decodeJwt, type JWTPayload } from 'jose';
4
-
5
- type TokenClaims<T> = Partial<JWTPayload & T>;
3
+ import { decodeJwt, type TokenClaims } from '../jwt.js';
6
4
 
7
5
  /**
8
6
  * A hook that retrieves the claims from the access token.
@@ -22,7 +20,7 @@ export function useTokenClaims<T = Record<string, unknown>>(): TokenClaims<T> {
22
20
  }
23
21
 
24
22
  try {
25
- return decodeJwt<T>(accessToken);
23
+ return decodeJwt<T>(accessToken).payload;
26
24
  } catch {
27
25
  return {};
28
26
  }
package/src/jwt.ts ADDED
@@ -0,0 +1,106 @@
1
+ /**
2
+ * JWT (JSON Web Token) Interface Definitions
3
+ */
4
+ export interface JWTHeader {
5
+ 'alg': string;
6
+ 'typ'?: string | undefined;
7
+ 'cty'?: string | undefined;
8
+ 'crit'?: Array<string | Exclude<keyof JWTHeader, 'crit'>> | undefined;
9
+ 'kid'?: string | undefined;
10
+ 'jku'?: string | undefined;
11
+ 'x5u'?: string | string[] | undefined;
12
+ 'x5t#S256'?: string | undefined;
13
+ 'x5t'?: string | undefined;
14
+ 'x5c'?: string | string[] | undefined;
15
+ }
16
+ /**
17
+ * JWT Payload Interface
18
+ */
19
+ export interface JWTPayload {
20
+ /**
21
+ * Session ID of the JWT, used to identify the session
22
+ */
23
+ sid: string;
24
+
25
+ /**
26
+ * Issuer of the JWT
27
+ */
28
+ iss: string;
29
+ /**
30
+ * Subject of the JWT
31
+ */
32
+ sub: string;
33
+ /**
34
+ * Audience of the JWT, can be a single string or an array of strings
35
+ */
36
+ aud?: string | string[];
37
+ /**
38
+ * Expiration time of the JWT, represented as a Unix timestamp
39
+ */
40
+ exp: number;
41
+ /**
42
+ * Issued at time of the JWT, represented as a Unix timestamp
43
+ */
44
+ iat: number;
45
+ /**
46
+ * JWT ID, a unique identifier for the JWT
47
+ */
48
+ jti: string;
49
+
50
+ /**
51
+ * Organization ID associated with the JWT
52
+ */
53
+ org_id?: string;
54
+
55
+ /**
56
+ * Role of the user associated with the JWT
57
+ */
58
+ role?: string;
59
+
60
+ /**
61
+ * Permissions granted to the user associated with the JWT
62
+ */
63
+ permissions?: string[];
64
+ }
65
+
66
+ export type TokenClaims<T> = Partial<JWTPayload & T>;
67
+
68
+ /**
69
+ * Decodes a base64url encoded string
70
+ * @param input The base64url string to decode
71
+ * @returns The decoded string
72
+ */
73
+ function decodeBase64Url(input: string): string {
74
+ const base64 = input.replace(/-/g, '+').replace(/_/g, '/');
75
+ const padding = '='.repeat((4 - (base64.length % 4)) % 4);
76
+ return atob(base64 + padding);
77
+ }
78
+
79
+ /**
80
+ * Decodes a JWT token and returns its header and payload
81
+ * @param token The JWT token to decode
82
+ * @return An object containing the decoded header and payload
83
+ * @throws Error if the token is not in a valid JWT format or if decoding fails
84
+ */
85
+ // should replace this with jose if we ever need to verify the JWT
86
+ export function decodeJwt<T = Record<string, unknown>>(
87
+ token: string,
88
+ ): {
89
+ header: JWTHeader;
90
+ payload: TokenClaims<T>;
91
+ } {
92
+ const parts = token.split('.');
93
+
94
+ if (parts.length !== 3) {
95
+ throw new Error('Invalid JWT format');
96
+ }
97
+
98
+ try {
99
+ const header = JSON.parse(decodeBase64Url(parts[0])) as JWTHeader;
100
+ const payload = JSON.parse(decodeBase64Url(parts[1])) as JWTPayload & T;
101
+
102
+ return { header, payload };
103
+ } catch (error) {
104
+ throw new Error(`Failed to decode JWT: ${error instanceof Error ? error.message : String(error)}`);
105
+ }
106
+ }
package/src/workos.ts CHANGED
@@ -2,7 +2,7 @@ import { WorkOS } from '@workos-inc/node';
2
2
  import { WORKOS_API_HOSTNAME, WORKOS_API_KEY, WORKOS_API_HTTPS, WORKOS_API_PORT } from './env-variables.js';
3
3
  import { lazy } from './utils.js';
4
4
 
5
- export const VERSION = '2.4.1';
5
+ export const VERSION = '2.4.3';
6
6
 
7
7
  const options = {
8
8
  apiHostname: WORKOS_API_HOSTNAME,