@workos-inc/authkit-nextjs 3.0.0 → 3.0.1
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 +29 -0
- package/dist/esm/actions.js +3 -4
- package/dist/esm/actions.js.map +1 -1
- package/dist/esm/auth.js +21 -2
- package/dist/esm/auth.js.map +1 -1
- package/dist/esm/authkit-callback-route.js +24 -15
- package/dist/esm/authkit-callback-route.js.map +1 -1
- package/dist/esm/cookie.js +5 -1
- package/dist/esm/cookie.js.map +1 -1
- package/dist/esm/pkce.js +22 -8
- package/dist/esm/pkce.js.map +1 -1
- package/dist/esm/session.js +14 -5
- package/dist/esm/session.js.map +1 -1
- package/dist/esm/types/actions.d.ts +2 -2
- package/dist/esm/types/cookie.d.ts +1 -0
- package/dist/esm/types/pkce.d.ts +5 -0
- package/package.json +2 -1
- package/src/actions.spec.ts +6 -10
- package/src/actions.ts +3 -4
- package/src/auth.spec.ts +19 -0
- package/src/auth.ts +20 -2
- package/src/authkit-callback-route.spec.ts +69 -7
- package/src/authkit-callback-route.ts +32 -17
- package/src/cookie.spec.ts +49 -0
- package/src/cookie.ts +7 -1
- package/src/pkce.spec.ts +26 -5
- package/src/pkce.ts +25 -8
- package/src/session.ts +18 -5
package/README.md
CHANGED
|
@@ -142,6 +142,26 @@ The `onSuccess` callback receives the following data:
|
|
|
142
142
|
|
|
143
143
|
**Note**: `authenticationMethod` is only provided during the initial authentication callback. It will not be available in subsequent requests or session refreshes.
|
|
144
144
|
|
|
145
|
+
### Sign-in endpoint
|
|
146
|
+
|
|
147
|
+
Create a route that initiates the AuthKit sign-in flow. This route is used as the **[Sign-in endpoint](https://workos.com/docs/authkit/nextjs/2-configure-your-project/configure-a-redirect-uri#sign-in-endpoint)** (also known as `initiate_login_uri`) in your WorkOS dashboard settings.
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
// app/sign-in/route.ts (or app/login/route.ts)
|
|
151
|
+
import { getSignInUrl } from '@workos-inc/authkit-nextjs';
|
|
152
|
+
import { redirect } from 'next/navigation';
|
|
153
|
+
|
|
154
|
+
export const GET = async () => {
|
|
155
|
+
const signInUrl = await getSignInUrl();
|
|
156
|
+
return redirect(signInUrl);
|
|
157
|
+
};
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
In the [WorkOS dashboard](https://dashboard.workos.com), go to **Redirects** and set the **Sign-in endpoint** to match this route (e.g., `http://localhost:3000/sign-in`).
|
|
161
|
+
|
|
162
|
+
> [!IMPORTANT]
|
|
163
|
+
> The sign-in endpoint is required for features like [impersonation](https://workos.com/docs/user-management/impersonation) to work correctly. Without it, WorkOS-initiated flows (such as impersonating a user from the dashboard) will fail because they cannot complete the PKCE/CSRF verification that this library enforces on every callback.
|
|
164
|
+
|
|
145
165
|
### Proxy / Middleware
|
|
146
166
|
|
|
147
167
|
This library relies on Next.js proxy (called "middleware" in Next.js ≤15) to provide session management for routes.
|
|
@@ -746,6 +766,9 @@ await signOut({ returnTo: 'https://your-app.com/signed-out' });
|
|
|
746
766
|
Render the `Impersonation` component in your app so that it is clear when someone is [impersonating a user](https://workos.com/docs/user-management/impersonation).
|
|
747
767
|
The component will display a frame with some information about the impersonated user, as well as a button to stop impersonating.
|
|
748
768
|
|
|
769
|
+
> [!IMPORTANT]
|
|
770
|
+
> Impersonation requires a configured **Sign-in endpoint** in your WorkOS dashboard. See the [sign-in endpoint](#sign-in-endpoint) setup instructions. Without it, impersonation from the WorkOS dashboard will fail with a `Missing required auth parameter` error.
|
|
771
|
+
|
|
749
772
|
```jsx
|
|
750
773
|
import { Impersonation, AuthKitProvider } from '@workos-inc/authkit-nextjs/components';
|
|
751
774
|
|
|
@@ -939,6 +962,12 @@ If the cookie is missing or doesn't match, authentication will fail with one of:
|
|
|
939
962
|
|
|
940
963
|
### Troubleshooting
|
|
941
964
|
|
|
965
|
+
#### `Missing required auth parameter` when impersonating from the WorkOS dashboard
|
|
966
|
+
|
|
967
|
+
This error occurs when WorkOS-initiated flows (like dashboard impersonation) redirect directly to your callback URL without going through your application's sign-in flow. Because this library enforces PKCE/CSRF verification on every callback, the request is rejected when the required `state` parameter is missing.
|
|
968
|
+
|
|
969
|
+
**Fix:** Configure a [sign-in endpoint](#sign-in-endpoint) in your WorkOS dashboard so that impersonation flows route through your app first, allowing PKCE/state to be set up before redirecting to WorkOS.
|
|
970
|
+
|
|
942
971
|
#### NEXT_REDIRECT error when using try/catch blocks
|
|
943
972
|
|
|
944
973
|
Wrapping a `withAuth({ ensureSignedIn: true })` call in a try/catch block will cause a `NEXT_REDIRECT` error. This is because `withAuth` will attempt to redirect the user to AuthKit if no session is detected and redirects in Next must be [called outside a try/catch](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#redirecting).
|
package/dist/esm/actions.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use server';
|
|
2
|
-
import { signOut, switchToOrganization } from './auth.js';
|
|
2
|
+
import { getSignInUrl, signOut, switchToOrganization } from './auth.js';
|
|
3
3
|
import { refreshSession, withAuth } from './session.js';
|
|
4
|
-
import { getAuthorizationUrl } from './get-authorization-url.js';
|
|
5
4
|
import { getWorkOS } from './workos.js';
|
|
6
5
|
/**
|
|
7
6
|
* This function is used to sanitize the auth object.
|
|
@@ -36,7 +35,7 @@ export const getAuthAction = async (options) => {
|
|
|
36
35
|
const auth = await withAuth();
|
|
37
36
|
const sanitized = sanitize(auth);
|
|
38
37
|
if (options?.ensureSignedIn && !auth.user) {
|
|
39
|
-
const signInUrl = await
|
|
38
|
+
const signInUrl = await getSignInUrl();
|
|
40
39
|
return { ...sanitized, signInUrl };
|
|
41
40
|
}
|
|
42
41
|
return sanitized;
|
|
@@ -47,7 +46,7 @@ export const refreshAuthAction = async ({ ensureSignedIn, organizationId, }) =>
|
|
|
47
46
|
const auth = await refreshSession({ organizationId });
|
|
48
47
|
const sanitized = sanitize(auth);
|
|
49
48
|
if (ensureSignedIn && !auth.user) {
|
|
50
|
-
const signInUrl = await
|
|
49
|
+
const signInUrl = await getSignInUrl();
|
|
51
50
|
return { ...sanitized, signInUrl };
|
|
52
51
|
}
|
|
53
52
|
return sanitized;
|
package/dist/esm/actions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/actions.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/actions.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAExE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOxC;;;;;GAKG;AACH,SAAS,QAAQ,CAAkC,KAAQ;IACzD,6DAA6D;IAC7D,MAAM,EAAE,WAAW,EAAE,GAAG,SAAS,EAAE,GAAG,KAAK,CAAC;IAC5C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,IAAI,EAAE;IAC3C,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAE,EAAE,QAAQ,KAA4B,EAAE,EAAE,EAAE;IACpF,MAAM,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC9B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EAAE,cAAsB,EAAE,EAAE;IACpE,OAAO,MAAM,SAAS,EAAE,CAAC,aAAa,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;AACzE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,OAAsC,EAAE,EAAE;IAC5E,+EAA+E;IAC/E,0EAA0E;IAC1E,0EAA0E;IAC1E,gDAAgD;IAChD,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEjC,IAAI,OAAO,EAAE,cAAc,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1C,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;QACvC,OAAO,EAAE,GAAG,SAAS,EAAE,SAAS,EAAE,CAAC;IACrC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,EACtC,cAAc,EACd,cAAc,GAIf,EAAE,EAAE;IACH,2EAA2E;IAC3E,2CAA2C;IAC3C,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAEjC,IAAI,cAAc,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;QACvC,OAAO,EAAE,GAAG,SAAS,EAAE,SAAS,EAAE,CAAC;IACrC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,EAAE,cAAsB,EAAE,OAAqC,EAAE,EAAE;IAChH,OAAO,QAAQ,CAAC,MAAM,oBAAoB,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;AACvE,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC9B,OAAO,IAAI,CAAC,WAAW,CAAC;AAC1B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB;IAC5C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAC;QACpC,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,iCAAiC,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACxG,OAAO;YACL,WAAW,EAAE,SAAS;YACtB,KAAK,EAAE,gCAAgC;SACxC,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/esm/auth.js
CHANGED
|
@@ -4,9 +4,9 @@ import { revalidatePath, revalidateTag } from 'next/cache';
|
|
|
4
4
|
import { cookies, headers } from 'next/headers';
|
|
5
5
|
import { redirect } from 'next/navigation';
|
|
6
6
|
import { WORKOS_COOKIE_NAME } from './env-variables.js';
|
|
7
|
-
import { getCookieOptions } from './cookie.js';
|
|
7
|
+
import { getCookieOptions, getPKCECookieOptions } from './cookie.js';
|
|
8
8
|
import { getAuthorizationUrl } from './get-authorization-url.js';
|
|
9
|
-
import { setPKCECookie } from './pkce.js';
|
|
9
|
+
import { PKCE_COOKIE_NAME, setPKCECookie } from './pkce.js';
|
|
10
10
|
import { getSessionFromCookie, refreshSession, withAuth } from './session.js';
|
|
11
11
|
import { getWorkOS } from './workos.js';
|
|
12
12
|
/**
|
|
@@ -70,6 +70,25 @@ export async function signOut({ returnTo } = {}) {
|
|
|
70
70
|
// Some environments (e.g., vinext) only accept a string cookie name
|
|
71
71
|
nextCookies.delete(cookieName);
|
|
72
72
|
}
|
|
73
|
+
// Clear any lingering PKCE verifier cookies so orphans from abandoned
|
|
74
|
+
// flows don't accumulate toward HTTP 431 or confuse future sign-ins.
|
|
75
|
+
const pkceOptions = getPKCECookieOptions();
|
|
76
|
+
for (const { name } of nextCookies.getAll()) {
|
|
77
|
+
if (!name.startsWith(PKCE_COOKIE_NAME))
|
|
78
|
+
continue;
|
|
79
|
+
try {
|
|
80
|
+
nextCookies.delete({
|
|
81
|
+
name,
|
|
82
|
+
domain: pkceOptions.domain,
|
|
83
|
+
path: pkceOptions.path,
|
|
84
|
+
sameSite: pkceOptions.sameSite,
|
|
85
|
+
secure: pkceOptions.secure,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
nextCookies.delete(name);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
73
92
|
if (sessionId) {
|
|
74
93
|
redirect(getWorkOS().userManagement.getLogoutUrl({ sessionId, returnTo }));
|
|
75
94
|
}
|
package/dist/esm/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/auth.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getPKCECookieOptions } from './cookie.js';
|
|
2
2
|
import { WORKOS_CLIENT_ID } from './env-variables.js';
|
|
3
|
-
import { PKCE_COOKIE_NAME, getStateFromPKCECookieValue } from './pkce.js';
|
|
3
|
+
import { PKCE_COOKIE_NAME, getPKCECookieNameForState, getStateFromPKCECookieValue } from './pkce.js';
|
|
4
4
|
import { saveSession } from './session.js';
|
|
5
5
|
import { errorResponseWithFallback, redirectWithFallback, setCachePreventionHeaders } from './utils.js';
|
|
6
6
|
import { getWorkOS } from './workos.js';
|
|
@@ -20,22 +20,25 @@ export function handleAuth(options = {}) {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
return async function GET(request) {
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
//
|
|
23
|
+
// Fall back to standard URL parsing when nextUrl is not available (e.g., vinext)
|
|
24
|
+
const requestUrl = request.nextUrl ?? new URL(request.url);
|
|
25
|
+
// Gather mandatory information
|
|
26
|
+
const code = requestUrl.searchParams.get('code');
|
|
27
|
+
const state = requestUrl.searchParams.get('state');
|
|
28
|
+
// We want to catch any & all errors and respond the same way, always
|
|
29
|
+
// destroying the 1-use PKCE cookie to prevent replay attacks or stale
|
|
30
|
+
// cookies affecting future auth attempts.
|
|
29
31
|
try {
|
|
30
|
-
// Fall back to standard URL parsing when nextUrl is not available (e.g., vinext)
|
|
31
|
-
const requestUrl = request.nextUrl ?? new URL(request.url);
|
|
32
|
-
// Gather mandatory information
|
|
33
|
-
const code = requestUrl.searchParams.get('code');
|
|
34
|
-
const state = requestUrl.searchParams.get('state');
|
|
35
|
-
const pkceCookie = request.cookies.get(PKCE_COOKIE_NAME)?.value;
|
|
36
32
|
if (!code || !state) {
|
|
37
33
|
throw new Error('Missing required auth parameter');
|
|
38
34
|
}
|
|
35
|
+
// Derive the flow-specific cookie name from the state param so each
|
|
36
|
+
// concurrent auth flow reads/deletes its own cookie, not a shared one.
|
|
37
|
+
// Fall back to the legacy shared cookie name so in-flight OAuth flows
|
|
38
|
+
// started on v3.0.x don't fail on the first callback after upgrade.
|
|
39
|
+
// Safe to remove once v3.0.x is unsupported.
|
|
40
|
+
const pkceCookieName = getPKCECookieNameForState(state);
|
|
41
|
+
const pkceCookie = request.cookies.get(pkceCookieName)?.value ?? request.cookies.get(PKCE_COOKIE_NAME)?.value;
|
|
39
42
|
// CSRF verification: both channels (cookie + URL state) must be present and match
|
|
40
43
|
if (!pkceCookie) {
|
|
41
44
|
throw new Error('Auth cookie missing — cannot verify OAuth state. Ensure Set-Cookie headers are propagated on redirects.');
|
|
@@ -70,7 +73,9 @@ export function handleAuth(options = {}) {
|
|
|
70
73
|
// This is to support Next.js 13.
|
|
71
74
|
const response = redirectWithFallback(url.toString());
|
|
72
75
|
preventCaching(response.headers);
|
|
73
|
-
|
|
76
|
+
// Always delete the PKCE cookie after handling the callback, regardless of success or error
|
|
77
|
+
// to avoid stale cookies affecting future auth attempts & prevent replays
|
|
78
|
+
response.headers.append('Set-Cookie', `${pkceCookieName}=; ${getPKCECookieOptions(request.url, true, true)}`);
|
|
74
79
|
await saveSession({ accessToken, refreshToken, user, impersonator }, request);
|
|
75
80
|
if (onSuccess) {
|
|
76
81
|
await onSuccess({
|
|
@@ -89,7 +94,11 @@ export function handleAuth(options = {}) {
|
|
|
89
94
|
catch (error) {
|
|
90
95
|
console.error('[AuthKit callback error]', error);
|
|
91
96
|
const response = await errorResponse(request, error);
|
|
92
|
-
|
|
97
|
+
// Always delete the PKCE cookie after handling the callback, regardless of success or error
|
|
98
|
+
// to avoid stale cookies affecting future auth attempts & prevent replays
|
|
99
|
+
if (state) {
|
|
100
|
+
response.headers.append('Set-Cookie', `${getPKCECookieNameForState(state)}=; ${getPKCECookieOptions(request.url, true, true)}`);
|
|
101
|
+
}
|
|
93
102
|
return response;
|
|
94
103
|
}
|
|
95
104
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authkit-callback-route.js","sourceRoot":"","sources":["../../src/authkit-callback-route.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"authkit-callback-route.js","sourceRoot":"","sources":["../../src/authkit-callback-route.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAC;AACrG,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACxG,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,SAAS,cAAc,CAAC,OAAgB;IACtC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9B,yBAAyB,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,UAA6B,EAAE;IACxD,MAAM,EAAE,cAAc,EAAE,oBAAoB,GAAG,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAE5F,iDAAiD;IACjD,IAAI,OAAO,EAAE,CAAC;QACZ,IAAI,CAAC;YACH,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QACnB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,OAAO,KAAK,UAAU,GAAG,CAAC,OAAoB;QAC5C,iFAAiF;QACjF,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAE3D,+BAA+B;QAC/B,MAAM,IAAI,GAAG,UAAU,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,UAAU,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEnD,qEAAqE;QACrE,sEAAsE;QACtE,0CAA0C;QAC1C,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;YACrD,CAAC;YAED,oEAAoE;YACpE,uEAAuE;YACvE,sEAAsE;YACtE,oEAAoE;YACpE,6CAA6C;YAC7C,MAAM,cAAc,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;YACxD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,KAAK,CAAC;YAE9G,kFAAkF;YAClF,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CACb,yGAAyG,CAC1G,CAAC;YACJ,CAAC;YAED,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;YAC1C,CAAC;YAED,MAAM,EACJ,YAAY,EACZ,WAAW,EACX,cAAc,EAAE,mBAAmB,GACpC,GAAG,MAAM,2BAA2B,CAAC,UAAU,CAAC,CAAC;YAElD,+EAA+E;YAC/E,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,cAAc,EAAE,GACxG,MAAM,SAAS,EAAE,CAAC,cAAc,CAAC,oBAAoB,CAAC;gBACpD,QAAQ,EAAE,gBAAgB;gBAC1B,IAAI;gBACJ,YAAY;aACb,CAAC,CAAC;YAEL,IAAI,CAAC,WAAW,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAChD,CAAC;YAED,4DAA4D;YAC5D,0EAA0E;YAC1E,4DAA4D;YAC5D,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;YAExE,iBAAiB;YACjB,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAChC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAEjC,uDAAuD;YACvD,MAAM,cAAc,GAAG,mBAAmB,IAAI,oBAAoB,CAAC;YAEnE,yDAAyD;YACzD,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAC;YAC3E,GAAG,CAAC,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC;YACxC,GAAG,CAAC,MAAM,GAAG,eAAe,CAAC,MAAM,CAAC;YAEpC,mEAAmE;YACnE,iCAAiC;YACjC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;YACtD,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAEjC,4FAA4F;YAC5F,0EAA0E;YAC1E,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,GAAG,cAAc,MAAM,oBAAoB,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;YAE9G,MAAM,WAAW,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,OAAO,CAAC,CAAC;YAE9E,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,SAAS,CAAC;oBACd,WAAW;oBACX,YAAY;oBACZ,IAAI;oBACJ,YAAY;oBACZ,WAAW;oBACX,oBAAoB;oBACpB,cAAc;oBACd,KAAK,EAAE,WAAW;iBACnB,CAAC,CAAC;YACL,CAAC;YAED,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;YACjD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAErD,4FAA4F;YAC5F,0EAA0E;YAC1E,IAAI,KAAK,EAAE,CAAC;gBACV,QAAQ,CAAC,OAAO,CAAC,MAAM,CACrB,YAAY,EACZ,GAAG,yBAAyB,CAAC,KAAK,CAAC,MAAM,oBAAoB,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CACzF,CAAC;YACJ,CAAC;YAED,OAAO,QAAQ,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,UAAU,aAAa,CAAC,OAAoB,EAAE,KAAe;QAChE,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YACnD,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACjC,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,MAAM,QAAQ,GAAG,yBAAyB,CAAC;YACzC,KAAK,EAAE;gBACL,OAAO,EAAE,sBAAsB;gBAC/B,WAAW,EAAE,8FAA8F;aAC5G;SACF,CAAC,CAAC;QAEH,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjC,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC"}
|
package/dist/esm/cookie.js
CHANGED
|
@@ -63,15 +63,19 @@ export function getCookieOptions(redirectUri, asString = false, expired = false)
|
|
|
63
63
|
domain: WORKOS_COOKIE_DOMAIN || '',
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
|
+
const PKCE_COOKIE_MAX_AGE = 600; // 10 minutes
|
|
66
67
|
export function getPKCECookieOptions(redirectUri, asString = false, expired = false) {
|
|
67
68
|
if (asString) {
|
|
68
69
|
const options = getCookieOptions(redirectUri, true, expired);
|
|
69
|
-
return options
|
|
70
|
+
return options
|
|
71
|
+
.replace(/SameSite=Strict/i, 'SameSite=Lax')
|
|
72
|
+
.replace(/Max-Age=\d+/, `Max-Age=${expired ? 0 : PKCE_COOKIE_MAX_AGE}`);
|
|
70
73
|
}
|
|
71
74
|
const options = getCookieOptions(redirectUri);
|
|
72
75
|
return {
|
|
73
76
|
...options,
|
|
74
77
|
sameSite: options.sameSite.toLowerCase() === 'strict' ? 'lax' : options.sameSite,
|
|
78
|
+
maxAge: expired ? 0 : PKCE_COOKIE_MAX_AGE,
|
|
75
79
|
};
|
|
76
80
|
}
|
|
77
81
|
export function getJwtCookie(body, requestUrlOrRedirectUri, expired) {
|
package/dist/esm/cookie.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cookie.js","sourceRoot":"","sources":["../../src/cookie.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAK5B,MAAM,kBAAkB,GAAG,EAAE,CAAC,CAAC,UAAU;AACzC,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAeD,MAAM,UAAU,gBAAgB,CAC9B,WAA2B,EAC3B,WAAoB,KAAK,EACzB,UAAmB,KAAK;IAExB,MAAM,QAAQ,GAAG,sBAAsB,IAAI,KAAK,CAAC;IACjD,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAE7B,MAAM,SAAS,GAAG,WAAW,IAAI,mBAAmB,CAAC;IACrD,oEAAoE;IACpE,iEAAiE;IACjE,IAAI,MAAe,CAAC;IACpB,IAAI,QAAQ,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;QACtC,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;SAAM,IAAI,SAAS,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;YAC/B,MAAM,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;YAClC,MAAM,GAAG,IAAI,CAAC;QAChB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,MAAc,CAAC;IACnB,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,GAAG,CAAC,CAAC;IACb,CAAC;SAAM,IAAI,qBAAqB,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;QACnD,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;IACjE,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;IAC9B,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC/F,MAAM,KAAK,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,YAAY,mBAAmB,EAAE,EAAE,WAAW,MAAM,EAAE,CAAC,CAAC;QAC7F,IAAI,oBAAoB,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,UAAU,oBAAoB,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO;QACL,IAAI,EAAE,GAAG;QACT,QAAQ,EAAE,IAAI;QACd,MAAM;QACN,QAAQ;QACR,sDAAsD;QACtD,2EAA2E;QAC3E,yDAAyD;QACzD,MAAM;QACN,MAAM,EAAE,oBAAoB,IAAI,EAAE;KACnC,CAAC;AACJ,CAAC;
|
|
1
|
+
{"version":3,"file":"cookie.js","sourceRoot":"","sources":["../../src/cookie.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAK5B,MAAM,kBAAkB,GAAG,EAAE,CAAC,CAAC,UAAU;AACzC,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAeD,MAAM,UAAU,gBAAgB,CAC9B,WAA2B,EAC3B,WAAoB,KAAK,EACzB,UAAmB,KAAK;IAExB,MAAM,QAAQ,GAAG,sBAAsB,IAAI,KAAK,CAAC;IACjD,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IAE7B,MAAM,SAAS,GAAG,WAAW,IAAI,mBAAmB,CAAC;IACrD,oEAAoE;IACpE,iEAAiE;IACjE,IAAI,MAAe,CAAC;IACpB,IAAI,QAAQ,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;QACtC,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;SAAM,IAAI,SAAS,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;YAC/B,MAAM,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;YAClC,MAAM,GAAG,IAAI,CAAC;QAChB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,MAAc,CAAC;IACnB,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,GAAG,CAAC,CAAC;IACb,CAAC;SAAM,IAAI,qBAAqB,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;QACnD,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;IACjE,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;IAC9B,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC/F,MAAM,KAAK,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,YAAY,mBAAmB,EAAE,EAAE,WAAW,MAAM,EAAE,CAAC,CAAC;QAC7F,IAAI,oBAAoB,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,UAAU,oBAAoB,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO;QACL,IAAI,EAAE,GAAG;QACT,QAAQ,EAAE,IAAI;QACd,MAAM;QACN,QAAQ;QACR,sDAAsD;QACtD,2EAA2E;QAC3E,yDAAyD;QACzD,MAAM;QACN,MAAM,EAAE,oBAAoB,IAAI,EAAE;KACnC,CAAC;AACJ,CAAC;AAED,MAAM,mBAAmB,GAAG,GAAG,CAAC,CAAC,aAAa;AAe9C,MAAM,UAAU,oBAAoB,CAClC,WAA2B,EAC3B,WAAoB,KAAK,EACzB,UAAmB,KAAK;IAExB,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,gBAAgB,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7D,OAAO,OAAO;aACX,OAAO,CAAC,kBAAkB,EAAE,cAAc,CAAC;aAC3C,OAAO,CAAC,aAAa,EAAE,WAAW,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,MAAM,OAAO,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC9C,OAAO;QACL,GAAG,OAAO;QACV,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ;QAChF,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB;KAC1C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAmB,EAAE,uBAAuC,EAAE,OAAiB;IAC1G,MAAM,MAAM,GAAG,GAAG,eAAe,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;IAEnE,mDAAmD;IACnD,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;IAE3D,IAAI,uBAAuB,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,uBAAuB,CAAC,CAAC;YAC7C,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,KAAK,WAAW,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,CAAC;YACjF,kEAAkE;YAClE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACP,wDAAwD;YACxD,MAAM,GAAG,YAAY,CAAC;YACtB,4DAA4D;YAC5D,MAAM,WAAW,GAAG,mBAAmB,CAAC;YACxC,IAAI,WAAW,EAAE,CAAC;gBAChB,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;oBACjC,MAAM,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;gBACrC,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,GAAG,KAAK,CAAC;gBACjB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;SAAM,IAAI,mBAAmB,EAAE,CAAC;QAC/B,6CAA6C;QAC7C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC;YACzC,MAAM,GAAG,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;QACrC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,GAAG,KAAK,CAAC;QACjB,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC;IAEhD,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,cAAc,EAAE,WAAW,MAAM,EAAE,CAAC,CAAC;IAE5D,mCAAmC;IACnC,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
package/dist/esm/pkce.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import fnv1a from '@sindresorhus/fnv1a';
|
|
1
2
|
import { unsealData } from 'iron-session';
|
|
2
3
|
import { cookies } from 'next/headers';
|
|
3
4
|
import * as v from 'valibot';
|
|
@@ -5,21 +6,34 @@ import { getPKCECookieOptions } from './cookie.js';
|
|
|
5
6
|
import { WORKOS_COOKIE_PASSWORD } from './env-variables.js';
|
|
6
7
|
import { StateSchema } from './interfaces.js';
|
|
7
8
|
export const PKCE_COOKIE_NAME = 'wos-auth-verifier';
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Short, deterministic hex fingerprint of an arbitrary string.
|
|
11
|
+
* Used to give each PKCE flow its own cookie name without depending
|
|
12
|
+
* on the internal format of the sealed state value
|
|
13
|
+
*/
|
|
14
|
+
function shortHash(input) {
|
|
15
|
+
// fnv1a returns a BigInt — use 32-bit variant so it fits safely in a Number
|
|
16
|
+
const hash = Number(fnv1a(input, { size: 32 }));
|
|
17
|
+
// Hex-encode and pad to a fixed 8-char width
|
|
18
|
+
return hash.toString(16).padStart(8, '0');
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Derive a flow-specific cookie name so concurrent auth flows don't overwrite
|
|
22
|
+
* each other's PKCE cookies. Uses an FNV-1a hash of the full sealed state
|
|
23
|
+
*/
|
|
24
|
+
export function getPKCECookieNameForState(state) {
|
|
25
|
+
return `${PKCE_COOKIE_NAME}-${shortHash(state)}`;
|
|
26
|
+
}
|
|
9
27
|
/**
|
|
10
28
|
* Set the PKCE verifier cookie in server action context.
|
|
11
29
|
* In middleware context, callers must set the cookie via Set-Cookie headers instead.
|
|
12
30
|
*/
|
|
13
31
|
export async function setPKCECookie(sealedState) {
|
|
14
32
|
const nextCookies = await cookies();
|
|
15
|
-
const
|
|
16
|
-
nextCookies.set(
|
|
17
|
-
|
|
18
|
-
path,
|
|
19
|
-
sameSite,
|
|
20
|
-
secure,
|
|
33
|
+
const options = getPKCECookieOptions();
|
|
34
|
+
nextCookies.set(getPKCECookieNameForState(sealedState), sealedState, {
|
|
35
|
+
...options,
|
|
21
36
|
httpOnly: true,
|
|
22
|
-
maxAge: PKCE_COOKIE_MAX_AGE,
|
|
23
37
|
});
|
|
24
38
|
}
|
|
25
39
|
/**
|
package/dist/esm/pkce.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../src/pkce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAS,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,CAAC,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../src/pkce.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,qBAAqB,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAS,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,CAAC,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AAEpD;;;;GAIG;AACH,SAAS,SAAS,CAAC,KAAa;IAC9B,4EAA4E;IAC5E,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAEhD,6CAA6C;IAC7C,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAAa;IACrD,OAAO,GAAG,gBAAgB,IAAI,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;AACnD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB;IACrD,MAAM,WAAW,GAAG,MAAM,OAAO,EAAE,CAAC;IACpC,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAC;IAEvC,WAAW,CAAC,GAAG,CAAC,yBAAyB,CAAC,WAAW,CAAC,EAAE,WAAW,EAAE;QACnE,GAAG,OAAO;QACV,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,WAAmB;IACnE,mFAAmF;IACnF,0FAA0F;IAC1F,mEAAmE;IACnE,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,WAAW,EAAE;QAC7C,QAAQ,EAAE,sBAAsB;KACjC,CAAC,CAAC;IAEH,OAAO,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;AACxC,CAAC"}
|
package/dist/esm/session.js
CHANGED
|
@@ -7,13 +7,22 @@ import { getCookieOptions, getJwtCookie, getPKCECookieOptions } from './cookie.j
|
|
|
7
7
|
import { WORKOS_CLIENT_ID, WORKOS_COOKIE_NAME, WORKOS_COOKIE_PASSWORD, WORKOS_REDIRECT_URI } from './env-variables.js';
|
|
8
8
|
import { TokenRefreshError, getSessionErrorContext } from './errors.js';
|
|
9
9
|
import { getAuthorizationUrl } from './get-authorization-url.js';
|
|
10
|
-
import {
|
|
10
|
+
import { getPKCECookieNameForState, setPKCECookie } from './pkce.js';
|
|
11
11
|
import { getWorkOS } from './workos.js';
|
|
12
12
|
import { parse, tokensToRegexp } from 'path-to-regexp';
|
|
13
13
|
import { handleAuthkitHeaders } from './middleware-helpers.js';
|
|
14
14
|
import { lazy, setCachePreventionHeaders } from './utils.js';
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
// Only set the PKCE cookie for initial document navigations — fetch/XHR/RSC/prefetch
|
|
16
|
+
// requests never follow cross-origin redirects so they'll never complete the OAuth
|
|
17
|
+
// flow and therefore don't need the cookie set.
|
|
18
|
+
// This prevents cookie bloat (HTTP 431) when multiple requests fire concurrently
|
|
19
|
+
// now that we are generating unique cookie names per flow, they add up quickly if
|
|
20
|
+
// we don't limit to just the initial navigation request
|
|
21
|
+
function appendPKCESetCookieHeader(request, headers, sealedState) {
|
|
22
|
+
if (!isInitialDocumentRequest(request)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
headers.append('Set-Cookie', `${getPKCECookieNameForState(sealedState)}=${sealedState}; ${getPKCECookieOptions(request.url, true)}`);
|
|
17
26
|
}
|
|
18
27
|
const sessionHeaderName = 'x-workos-session';
|
|
19
28
|
const middlewareHeaderName = 'x-workos-middleware';
|
|
@@ -146,7 +155,7 @@ async function updateSession(request, options = { debug: false }) {
|
|
|
146
155
|
redirectUri: options.redirectUri || WORKOS_REDIRECT_URI,
|
|
147
156
|
screenHint: options.screenHint,
|
|
148
157
|
});
|
|
149
|
-
appendPKCESetCookieHeader(newRequestHeaders, sealedState
|
|
158
|
+
appendPKCESetCookieHeader(request, newRequestHeaders, sealedState);
|
|
150
159
|
return {
|
|
151
160
|
session: { user: null },
|
|
152
161
|
headers: newRequestHeaders,
|
|
@@ -247,7 +256,7 @@ async function updateSession(request, options = { debug: false }) {
|
|
|
247
256
|
returnPathname: getReturnPathname(request.url),
|
|
248
257
|
redirectUri: options.redirectUri || WORKOS_REDIRECT_URI,
|
|
249
258
|
});
|
|
250
|
-
appendPKCESetCookieHeader(newRequestHeaders, sealedState
|
|
259
|
+
appendPKCESetCookieHeader(request, newRequestHeaders, sealedState);
|
|
251
260
|
return {
|
|
252
261
|
session: { user: null },
|
|
253
262
|
headers: newRequestHeaders,
|
package/dist/esm/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ export declare const getOrganizationAction: (organizationId: string) => Promise<
|
|
|
16
16
|
export declare const getAuthAction: (options?: {
|
|
17
17
|
ensureSignedIn?: boolean;
|
|
18
18
|
}) => Promise<Omit<UserInfo | NoUserInfo, "accessToken"> | {
|
|
19
|
-
signInUrl:
|
|
19
|
+
signInUrl: string;
|
|
20
20
|
organizationId?: string | undefined;
|
|
21
21
|
role?: string | undefined;
|
|
22
22
|
roles?: string[] | undefined;
|
|
@@ -31,7 +31,7 @@ export declare const refreshAuthAction: ({ ensureSignedIn, organizationId, }: {
|
|
|
31
31
|
ensureSignedIn?: boolean;
|
|
32
32
|
organizationId?: string;
|
|
33
33
|
}) => Promise<Omit<UserInfo | NoUserInfo, "accessToken"> | {
|
|
34
|
-
signInUrl:
|
|
34
|
+
signInUrl: string;
|
|
35
35
|
organizationId?: string | undefined;
|
|
36
36
|
role?: string | undefined;
|
|
37
37
|
roles?: string[] | undefined;
|
|
@@ -8,6 +8,7 @@ export declare function getCookieOptions(redirectUri?: string | null, asString?:
|
|
|
8
8
|
* Cookie options for the PKCE verifier cookie.
|
|
9
9
|
* 'strict' blocks the cookie on the cross-site redirect back from WorkOS; downgrade to 'lax'.
|
|
10
10
|
* 'none' is more permissive and must be preserved for iframe/cross-origin embed flows.
|
|
11
|
+
* Max-age is always capped to 10 minutes — PKCE cookies are single-use and short-lived.
|
|
11
12
|
*/
|
|
12
13
|
export declare function getPKCECookieOptions(): CookieOptions;
|
|
13
14
|
export declare function getPKCECookieOptions(redirectUri: string | null | undefined, asString: true, expired?: boolean): string;
|
package/dist/esm/types/pkce.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { State } from './interfaces.js';
|
|
2
2
|
export declare const PKCE_COOKIE_NAME = "wos-auth-verifier";
|
|
3
|
+
/**
|
|
4
|
+
* Derive a flow-specific cookie name so concurrent auth flows don't overwrite
|
|
5
|
+
* each other's PKCE cookies. Uses an FNV-1a hash of the full sealed state
|
|
6
|
+
*/
|
|
7
|
+
export declare function getPKCECookieNameForState(state: string): string;
|
|
3
8
|
/**
|
|
4
9
|
* Set the PKCE verifier cookie in server action context.
|
|
5
10
|
* In middleware context, callers must set the cookie via Set-Cookie headers instead.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workos-inc/authkit-nextjs",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Authentication and session helpers for using WorkOS & AuthKit with Next.js",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
+
"@sindresorhus/fnv1a": "^3.1.0",
|
|
26
27
|
"@workos-inc/node": "^8.9.0",
|
|
27
28
|
"iron-session": "^8.0.4",
|
|
28
29
|
"jose": "^5.10.0",
|
package/src/actions.spec.ts
CHANGED
|
@@ -8,12 +8,12 @@ import {
|
|
|
8
8
|
getAccessTokenAction,
|
|
9
9
|
refreshAccessTokenAction,
|
|
10
10
|
} from '../src/actions.js';
|
|
11
|
-
import { signOut, switchToOrganization } from './auth.js';
|
|
11
|
+
import { getSignInUrl, signOut, switchToOrganization } from './auth.js';
|
|
12
12
|
import { getWorkOS } from '../src/workos.js';
|
|
13
13
|
import { withAuth, refreshSession } from '../src/session.js';
|
|
14
|
-
import { getAuthorizationUrl } from '../src/get-authorization-url.js';
|
|
15
14
|
|
|
16
15
|
vi.mock('../src/auth.js', () => ({
|
|
16
|
+
getSignInUrl: vi.fn().mockResolvedValue('https://api.workos.com/authorize?...'),
|
|
17
17
|
signOut: vi.fn().mockResolvedValue(true),
|
|
18
18
|
switchToOrganization: vi.fn().mockResolvedValue({ organizationId: 'org_123' }),
|
|
19
19
|
}));
|
|
@@ -34,10 +34,6 @@ vi.mock('../src/session.js', () => ({
|
|
|
34
34
|
refreshSession: vi.fn().mockResolvedValue({ user: 'testUser', accessToken: 'refreshed_token' }),
|
|
35
35
|
}));
|
|
36
36
|
|
|
37
|
-
vi.mock('../src/get-authorization-url.js', () => ({
|
|
38
|
-
getAuthorizationUrl: vi.fn().mockResolvedValue('https://api.workos.com/authorize?...'),
|
|
39
|
-
}));
|
|
40
|
-
|
|
41
37
|
describe('actions', () => {
|
|
42
38
|
const workos = getWorkOS();
|
|
43
39
|
|
|
@@ -94,13 +90,13 @@ describe('actions', () => {
|
|
|
94
90
|
it('should return signInUrl when ensureSignedIn is true and no user', async () => {
|
|
95
91
|
vi.mocked(withAuth).mockResolvedValueOnce({ user: null });
|
|
96
92
|
const result = await getAuthAction({ ensureSignedIn: true });
|
|
97
|
-
expect(
|
|
93
|
+
expect(getSignInUrl).toHaveBeenCalled();
|
|
98
94
|
expect(result).toEqual({ user: null, signInUrl: 'https://api.workos.com/authorize?...' });
|
|
99
95
|
});
|
|
100
96
|
|
|
101
97
|
it('should not return signInUrl when ensureSignedIn is true and user exists', async () => {
|
|
102
98
|
const result = await getAuthAction({ ensureSignedIn: true });
|
|
103
|
-
expect(
|
|
99
|
+
expect(getSignInUrl).not.toHaveBeenCalled();
|
|
104
100
|
expect(result).toEqual({ user: 'testUser', sessionId: 'session_123' });
|
|
105
101
|
});
|
|
106
102
|
});
|
|
@@ -121,13 +117,13 @@ describe('actions', () => {
|
|
|
121
117
|
it('should return signInUrl when ensureSignedIn is true and no user', async () => {
|
|
122
118
|
vi.mocked(refreshSession).mockResolvedValueOnce({ user: null });
|
|
123
119
|
const result = await refreshAuthAction({ ensureSignedIn: true });
|
|
124
|
-
expect(
|
|
120
|
+
expect(getSignInUrl).toHaveBeenCalled();
|
|
125
121
|
expect(result).toEqual({ user: null, signInUrl: 'https://api.workos.com/authorize?...' });
|
|
126
122
|
});
|
|
127
123
|
|
|
128
124
|
it('should not return signInUrl when ensureSignedIn is true and user exists', async () => {
|
|
129
125
|
const result = await refreshAuthAction({ ensureSignedIn: true });
|
|
130
|
-
expect(
|
|
126
|
+
expect(getSignInUrl).not.toHaveBeenCalled();
|
|
131
127
|
expect(result).toEqual({ user: 'testUser', sessionId: 'session_123' });
|
|
132
128
|
});
|
|
133
129
|
});
|
package/src/actions.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import { signOut, switchToOrganization } from './auth.js';
|
|
3
|
+
import { getSignInUrl, signOut, switchToOrganization } from './auth.js';
|
|
4
4
|
import { NoUserInfo, UserInfo, SwitchToOrganizationOptions } from './interfaces.js';
|
|
5
5
|
import { refreshSession, withAuth } from './session.js';
|
|
6
|
-
import { getAuthorizationUrl } from './get-authorization-url.js';
|
|
7
6
|
import { getWorkOS } from './workos.js';
|
|
8
7
|
|
|
9
8
|
export interface RefreshAccessTokenActionResult {
|
|
@@ -49,7 +48,7 @@ export const getAuthAction = async (options?: { ensureSignedIn?: boolean }) => {
|
|
|
49
48
|
const sanitized = sanitize(auth);
|
|
50
49
|
|
|
51
50
|
if (options?.ensureSignedIn && !auth.user) {
|
|
52
|
-
const signInUrl = await
|
|
51
|
+
const signInUrl = await getSignInUrl();
|
|
53
52
|
return { ...sanitized, signInUrl };
|
|
54
53
|
}
|
|
55
54
|
|
|
@@ -69,7 +68,7 @@ export const refreshAuthAction = async ({
|
|
|
69
68
|
const sanitized = sanitize(auth);
|
|
70
69
|
|
|
71
70
|
if (ensureSignedIn && !auth.user) {
|
|
72
|
-
const signInUrl = await
|
|
71
|
+
const signInUrl = await getSignInUrl();
|
|
73
72
|
return { ...sanitized, signInUrl };
|
|
74
73
|
}
|
|
75
74
|
|
package/src/auth.spec.ts
CHANGED
|
@@ -274,6 +274,25 @@ describe('auth.ts', () => {
|
|
|
274
274
|
expect(sessionCookie).toBeUndefined();
|
|
275
275
|
});
|
|
276
276
|
|
|
277
|
+
it('should clear lingering PKCE verifier cookies (legacy and per-flow)', async () => {
|
|
278
|
+
const nextCookies = await cookies();
|
|
279
|
+
const nextHeaders = await headers();
|
|
280
|
+
|
|
281
|
+
nextHeaders.set('x-workos-middleware', 'true');
|
|
282
|
+
nextCookies.set('wos-session', 'foo');
|
|
283
|
+
nextCookies.set('wos-auth-verifier', 'legacy-state');
|
|
284
|
+
nextCookies.set('wos-auth-verifier-a1b2c3d4', 'flow-a-state');
|
|
285
|
+
nextCookies.set('wos-auth-verifier-deadbeef', 'flow-b-state');
|
|
286
|
+
nextCookies.set('unrelated-cookie', 'keep-me');
|
|
287
|
+
|
|
288
|
+
await signOut();
|
|
289
|
+
|
|
290
|
+
expect(nextCookies.get('wos-auth-verifier')).toBeUndefined();
|
|
291
|
+
expect(nextCookies.get('wos-auth-verifier-a1b2c3d4')).toBeUndefined();
|
|
292
|
+
expect(nextCookies.get('wos-auth-verifier-deadbeef')).toBeUndefined();
|
|
293
|
+
expect(nextCookies.get('unrelated-cookie')?.value).toBe('keep-me');
|
|
294
|
+
});
|
|
295
|
+
|
|
277
296
|
describe('when given a `returnTo` parameter', () => {
|
|
278
297
|
it('passes the `returnTo` through to the `getLogoutUrl` call', async () => {
|
|
279
298
|
vi.spyOn(workos.userManagement, 'getLogoutUrl').mockReturnValue(
|
package/src/auth.ts
CHANGED
|
@@ -5,10 +5,10 @@ import { revalidatePath, revalidateTag } from 'next/cache';
|
|
|
5
5
|
import { cookies, headers } from 'next/headers';
|
|
6
6
|
import { redirect } from 'next/navigation';
|
|
7
7
|
import { WORKOS_COOKIE_NAME } from './env-variables.js';
|
|
8
|
-
import { getCookieOptions } from './cookie.js';
|
|
8
|
+
import { getCookieOptions, getPKCECookieOptions } from './cookie.js';
|
|
9
9
|
import { getAuthorizationUrl } from './get-authorization-url.js';
|
|
10
10
|
import type { AccessToken, GetAuthURLOptions, SwitchToOrganizationOptions, UserInfo } from './interfaces.js';
|
|
11
|
-
import { setPKCECookie } from './pkce.js';
|
|
11
|
+
import { PKCE_COOKIE_NAME, setPKCECookie } from './pkce.js';
|
|
12
12
|
import { getSessionFromCookie, refreshSession, withAuth } from './session.js';
|
|
13
13
|
import { getWorkOS } from './workos.js';
|
|
14
14
|
|
|
@@ -80,6 +80,24 @@ export async function signOut({ returnTo }: { returnTo?: string } = {}) {
|
|
|
80
80
|
nextCookies.delete(cookieName);
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
// Clear any lingering PKCE verifier cookies so orphans from abandoned
|
|
84
|
+
// flows don't accumulate toward HTTP 431 or confuse future sign-ins.
|
|
85
|
+
const pkceOptions = getPKCECookieOptions();
|
|
86
|
+
for (const { name } of nextCookies.getAll()) {
|
|
87
|
+
if (!name.startsWith(PKCE_COOKIE_NAME)) continue;
|
|
88
|
+
try {
|
|
89
|
+
nextCookies.delete({
|
|
90
|
+
name,
|
|
91
|
+
domain: pkceOptions.domain,
|
|
92
|
+
path: pkceOptions.path,
|
|
93
|
+
sameSite: pkceOptions.sameSite,
|
|
94
|
+
secure: pkceOptions.secure,
|
|
95
|
+
});
|
|
96
|
+
} catch {
|
|
97
|
+
nextCookies.delete(name);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
83
101
|
if (sessionId) {
|
|
84
102
|
redirect(getWorkOS().userManagement.getLogoutUrl({ sessionId, returnTo }));
|
|
85
103
|
} else {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Mock } from 'vitest';
|
|
2
2
|
import { getWorkOS } from './workos.js';
|
|
3
3
|
import { handleAuth } from './authkit-callback-route.js';
|
|
4
|
+
import { getPKCECookieNameForState } from './pkce.js';
|
|
4
5
|
import { getSessionFromCookie, saveSession } from './session.js';
|
|
5
6
|
import { NextRequest, NextResponse } from 'next/server';
|
|
6
7
|
import { sealData } from 'iron-session';
|
|
@@ -56,7 +57,7 @@ describe('authkit-callback-route', () => {
|
|
|
56
57
|
|
|
57
58
|
async function setAuthCookie(req: NextRequest, state: State): Promise<string> {
|
|
58
59
|
const sealedState = await sealData(state, { password: process.env.WORKOS_COOKIE_PASSWORD! });
|
|
59
|
-
req.cookies.set(
|
|
60
|
+
req.cookies.set(getPKCECookieNameForState(sealedState), sealedState);
|
|
60
61
|
return sealedState;
|
|
61
62
|
}
|
|
62
63
|
|
|
@@ -548,10 +549,11 @@ describe('authkit-callback-route', () => {
|
|
|
548
549
|
it('should return an error response when PKCE cookie is corrupted', async () => {
|
|
549
550
|
vi.mocked(workos.userManagement.authenticateWithCode).mockResolvedValue(mockAuthResponse);
|
|
550
551
|
|
|
551
|
-
// Set a corrupted cookie
|
|
552
|
-
|
|
552
|
+
// Set a corrupted cookie using the flow-specific name
|
|
553
|
+
const corruptedState = 'not-a-valid-sealed-value';
|
|
554
|
+
request.cookies.set(getPKCECookieNameForState(corruptedState), corruptedState);
|
|
553
555
|
request.nextUrl.searchParams.set('code', 'test-code');
|
|
554
|
-
request.nextUrl.searchParams.set('state',
|
|
556
|
+
request.nextUrl.searchParams.set('state', corruptedState);
|
|
555
557
|
|
|
556
558
|
const handler = handleAuth();
|
|
557
559
|
const response = await handler(request);
|
|
@@ -570,11 +572,12 @@ describe('authkit-callback-route', () => {
|
|
|
570
572
|
const handler = handleAuth();
|
|
571
573
|
const response = await handler(request);
|
|
572
574
|
|
|
573
|
-
// The response should be a redirect (success) and have a Set-Cookie header to delete the PKCE cookie
|
|
575
|
+
// The response should be a redirect (success) and have a Set-Cookie header to delete the flow-specific PKCE cookie
|
|
574
576
|
expect(response.status).toBe(307);
|
|
575
577
|
|
|
578
|
+
const flowCookieName = getPKCECookieNameForState(sealedState);
|
|
576
579
|
const setCookieHeaders = response.headers.getSetCookie();
|
|
577
|
-
const pkceDeletionCookie = setCookieHeaders.find((c: string) => c.startsWith(
|
|
580
|
+
const pkceDeletionCookie = setCookieHeaders.find((c: string) => c.startsWith(`${flowCookieName}=`));
|
|
578
581
|
expect(pkceDeletionCookie).toBeDefined();
|
|
579
582
|
expect(pkceDeletionCookie).toContain('Max-Age=0');
|
|
580
583
|
});
|
|
@@ -590,11 +593,70 @@ describe('authkit-callback-route', () => {
|
|
|
590
593
|
const response = await handler(request);
|
|
591
594
|
|
|
592
595
|
expect(response.status).toBe(500);
|
|
596
|
+
const flowCookieName = getPKCECookieNameForState(sealedState);
|
|
593
597
|
const setCookieHeaders = response.headers.getSetCookie();
|
|
594
|
-
const pkceDeletionCookie = setCookieHeaders.find((c: string) => c.startsWith(
|
|
598
|
+
const pkceDeletionCookie = setCookieHeaders.find((c: string) => c.startsWith(`${flowCookieName}=`));
|
|
595
599
|
expect(pkceDeletionCookie).toBeDefined();
|
|
596
600
|
expect(pkceDeletionCookie).toContain('Max-Age=0');
|
|
597
601
|
});
|
|
602
|
+
|
|
603
|
+
it('should isolate concurrent auth flows using per-flow cookie names', async () => {
|
|
604
|
+
vi.mocked(workos.userManagement.authenticateWithCode).mockResolvedValue(mockAuthResponse);
|
|
605
|
+
|
|
606
|
+
// Simulate two concurrent auth flows with different sealed states
|
|
607
|
+
const sealedStateA = await sealData(
|
|
608
|
+
{ nonce: 'nonce-a', codeVerifier: 'verifier-a' },
|
|
609
|
+
{ password: process.env.WORKOS_COOKIE_PASSWORD! },
|
|
610
|
+
);
|
|
611
|
+
const sealedStateB = await sealData(
|
|
612
|
+
{ nonce: 'nonce-b', codeVerifier: 'verifier-b' },
|
|
613
|
+
{ password: process.env.WORKOS_COOKIE_PASSWORD! },
|
|
614
|
+
);
|
|
615
|
+
|
|
616
|
+
// Both cookies exist on the request (set by different middleware redirects)
|
|
617
|
+
request.cookies.set(getPKCECookieNameForState(sealedStateA), sealedStateA);
|
|
618
|
+
request.cookies.set(getPKCECookieNameForState(sealedStateB), sealedStateB);
|
|
619
|
+
|
|
620
|
+
// Callback for flow A — should find its own cookie
|
|
621
|
+
request.nextUrl.searchParams.set('code', 'code-a');
|
|
622
|
+
request.nextUrl.searchParams.set('state', sealedStateA);
|
|
623
|
+
|
|
624
|
+
const handler = handleAuth();
|
|
625
|
+
const response = await handler(request);
|
|
626
|
+
|
|
627
|
+
expect(response.status).toBe(307);
|
|
628
|
+
expect(workos.userManagement.authenticateWithCode).toHaveBeenCalledWith(
|
|
629
|
+
expect.objectContaining({ codeVerifier: 'verifier-a' }),
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
// Flow B's cookie should NOT have been deleted
|
|
633
|
+
const setCookieHeaders = response.headers.getSetCookie();
|
|
634
|
+
const flowBCookieName = getPKCECookieNameForState(sealedStateB);
|
|
635
|
+
const flowBDeletion = setCookieHeaders.find((c: string) => c.startsWith(`${flowBCookieName}=`));
|
|
636
|
+
expect(flowBDeletion).toBeUndefined();
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
it('should fall back to the legacy shared PKCE cookie for v3.0.x in-flight flows', async () => {
|
|
640
|
+
vi.mocked(workos.userManagement.authenticateWithCode).mockResolvedValue(mockAuthResponse);
|
|
641
|
+
|
|
642
|
+
const sealedState = await sealData(
|
|
643
|
+
{ nonce: 'legacy', codeVerifier: 'legacy-verifier' },
|
|
644
|
+
{ password: process.env.WORKOS_COOKIE_PASSWORD! },
|
|
645
|
+
);
|
|
646
|
+
|
|
647
|
+
// Simulate a user mid-OAuth on v3.0.x: only the legacy cookie name exists
|
|
648
|
+
request.cookies.set('wos-auth-verifier', sealedState);
|
|
649
|
+
request.nextUrl.searchParams.set('code', 'test-code');
|
|
650
|
+
request.nextUrl.searchParams.set('state', sealedState);
|
|
651
|
+
|
|
652
|
+
const handler = handleAuth();
|
|
653
|
+
const response = await handler(request);
|
|
654
|
+
|
|
655
|
+
expect(response.status).toBe(307);
|
|
656
|
+
expect(workos.userManagement.authenticateWithCode).toHaveBeenCalledWith(
|
|
657
|
+
expect.objectContaining({ codeVerifier: 'legacy-verifier' }),
|
|
658
|
+
);
|
|
659
|
+
});
|
|
598
660
|
});
|
|
599
661
|
});
|
|
600
662
|
});
|
|
@@ -2,7 +2,7 @@ import { NextRequest } from 'next/server';
|
|
|
2
2
|
import { getPKCECookieOptions } from './cookie.js';
|
|
3
3
|
import { WORKOS_CLIENT_ID } from './env-variables.js';
|
|
4
4
|
import { HandleAuthOptions } from './interfaces.js';
|
|
5
|
-
import { PKCE_COOKIE_NAME, getStateFromPKCECookieValue } from './pkce.js';
|
|
5
|
+
import { PKCE_COOKIE_NAME, getPKCECookieNameForState, getStateFromPKCECookieValue } from './pkce.js';
|
|
6
6
|
import { saveSession } from './session.js';
|
|
7
7
|
import { errorResponseWithFallback, redirectWithFallback, setCachePreventionHeaders } from './utils.js';
|
|
8
8
|
import { getWorkOS } from './workos.js';
|
|
@@ -25,26 +25,29 @@ export function handleAuth(options: HandleAuthOptions = {}) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
return async function GET(request: NextRequest) {
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
const deleteCookie = `${PKCE_COOKIE_NAME}=; ${getPKCECookieOptions(request.url, true, true)}`;
|
|
28
|
+
// Fall back to standard URL parsing when nextUrl is not available (e.g., vinext)
|
|
29
|
+
const requestUrl = request.nextUrl ?? new URL(request.url);
|
|
31
30
|
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
// Fall back to standard URL parsing when nextUrl is not available (e.g., vinext)
|
|
37
|
-
const requestUrl = request.nextUrl ?? new URL(request.url);
|
|
38
|
-
|
|
39
|
-
// Gather mandatory information
|
|
40
|
-
const code = requestUrl.searchParams.get('code');
|
|
41
|
-
const state = requestUrl.searchParams.get('state');
|
|
42
|
-
const pkceCookie = request.cookies.get(PKCE_COOKIE_NAME)?.value;
|
|
31
|
+
// Gather mandatory information
|
|
32
|
+
const code = requestUrl.searchParams.get('code');
|
|
33
|
+
const state = requestUrl.searchParams.get('state');
|
|
43
34
|
|
|
35
|
+
// We want to catch any & all errors and respond the same way, always
|
|
36
|
+
// destroying the 1-use PKCE cookie to prevent replay attacks or stale
|
|
37
|
+
// cookies affecting future auth attempts.
|
|
38
|
+
try {
|
|
44
39
|
if (!code || !state) {
|
|
45
40
|
throw new Error('Missing required auth parameter');
|
|
46
41
|
}
|
|
47
42
|
|
|
43
|
+
// Derive the flow-specific cookie name from the state param so each
|
|
44
|
+
// concurrent auth flow reads/deletes its own cookie, not a shared one.
|
|
45
|
+
// Fall back to the legacy shared cookie name so in-flight OAuth flows
|
|
46
|
+
// started on v3.0.x don't fail on the first callback after upgrade.
|
|
47
|
+
// Safe to remove once v3.0.x is unsupported.
|
|
48
|
+
const pkceCookieName = getPKCECookieNameForState(state);
|
|
49
|
+
const pkceCookie = request.cookies.get(pkceCookieName)?.value ?? request.cookies.get(PKCE_COOKIE_NAME)?.value;
|
|
50
|
+
|
|
48
51
|
// CSRF verification: both channels (cookie + URL state) must be present and match
|
|
49
52
|
if (!pkceCookie) {
|
|
50
53
|
throw new Error(
|
|
@@ -95,7 +98,10 @@ export function handleAuth(options: HandleAuthOptions = {}) {
|
|
|
95
98
|
// This is to support Next.js 13.
|
|
96
99
|
const response = redirectWithFallback(url.toString());
|
|
97
100
|
preventCaching(response.headers);
|
|
98
|
-
|
|
101
|
+
|
|
102
|
+
// Always delete the PKCE cookie after handling the callback, regardless of success or error
|
|
103
|
+
// to avoid stale cookies affecting future auth attempts & prevent replays
|
|
104
|
+
response.headers.append('Set-Cookie', `${pkceCookieName}=; ${getPKCECookieOptions(request.url, true, true)}`);
|
|
99
105
|
|
|
100
106
|
await saveSession({ accessToken, refreshToken, user, impersonator }, request);
|
|
101
107
|
|
|
@@ -116,7 +122,16 @@ export function handleAuth(options: HandleAuthOptions = {}) {
|
|
|
116
122
|
} catch (error) {
|
|
117
123
|
console.error('[AuthKit callback error]', error);
|
|
118
124
|
const response = await errorResponse(request, error);
|
|
119
|
-
|
|
125
|
+
|
|
126
|
+
// Always delete the PKCE cookie after handling the callback, regardless of success or error
|
|
127
|
+
// to avoid stale cookies affecting future auth attempts & prevent replays
|
|
128
|
+
if (state) {
|
|
129
|
+
response.headers.append(
|
|
130
|
+
'Set-Cookie',
|
|
131
|
+
`${getPKCECookieNameForState(state)}=; ${getPKCECookieOptions(request.url, true, true)}`,
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
120
135
|
return response;
|
|
121
136
|
}
|
|
122
137
|
};
|
package/src/cookie.spec.ts
CHANGED
|
@@ -278,4 +278,53 @@ describe('cookie.ts', () => {
|
|
|
278
278
|
expect(ipCookie).not.toContain('Secure');
|
|
279
279
|
});
|
|
280
280
|
});
|
|
281
|
+
|
|
282
|
+
describe('getPKCECookieOptions', () => {
|
|
283
|
+
it('should use 10-minute max-age, not the session cookie max-age', async () => {
|
|
284
|
+
const { getPKCECookieOptions } = await import('./cookie');
|
|
285
|
+
|
|
286
|
+
const options = getPKCECookieOptions();
|
|
287
|
+
|
|
288
|
+
expect(options).toEqual(expect.objectContaining({ maxAge: 600 }));
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('should use 10-minute max-age in string format', async () => {
|
|
292
|
+
const { getPKCECookieOptions } = await import('./cookie');
|
|
293
|
+
|
|
294
|
+
const options = getPKCECookieOptions('http://localhost:3000', true);
|
|
295
|
+
|
|
296
|
+
expect(options).toContain('Max-Age=600');
|
|
297
|
+
expect(options).not.toContain('Max-Age=34560000');
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it('should use max-age 0 when expired in object format', async () => {
|
|
301
|
+
const { getPKCECookieOptions } = await import('./cookie');
|
|
302
|
+
|
|
303
|
+
const options = getPKCECookieOptions(undefined, false, true);
|
|
304
|
+
|
|
305
|
+
expect(options).toEqual(expect.objectContaining({ maxAge: 0 }));
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('should use max-age 0 when expired in string format', async () => {
|
|
309
|
+
const { getPKCECookieOptions } = await import('./cookie');
|
|
310
|
+
|
|
311
|
+
const options = getPKCECookieOptions('http://localhost:3000', true, true);
|
|
312
|
+
|
|
313
|
+
expect(options).toContain('Max-Age=0');
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('should downgrade SameSite=Strict to Lax', async () => {
|
|
317
|
+
const envVars = await import('./env-variables');
|
|
318
|
+
Object.defineProperty(envVars, 'WORKOS_COOKIE_SAMESITE', { value: 'strict' });
|
|
319
|
+
|
|
320
|
+
const { getPKCECookieOptions } = await import('./cookie');
|
|
321
|
+
|
|
322
|
+
const objectOptions = getPKCECookieOptions();
|
|
323
|
+
expect(objectOptions).toEqual(expect.objectContaining({ sameSite: 'lax' }));
|
|
324
|
+
|
|
325
|
+
const stringOptions = getPKCECookieOptions('http://localhost:3000', true);
|
|
326
|
+
expect(stringOptions).toContain('SameSite=Lax');
|
|
327
|
+
expect(stringOptions).not.toContain('SameSite=Strict');
|
|
328
|
+
});
|
|
329
|
+
});
|
|
281
330
|
});
|
package/src/cookie.ts
CHANGED
|
@@ -92,10 +92,13 @@ export function getCookieOptions(
|
|
|
92
92
|
};
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
const PKCE_COOKIE_MAX_AGE = 600; // 10 minutes
|
|
96
|
+
|
|
95
97
|
/**
|
|
96
98
|
* Cookie options for the PKCE verifier cookie.
|
|
97
99
|
* 'strict' blocks the cookie on the cross-site redirect back from WorkOS; downgrade to 'lax'.
|
|
98
100
|
* 'none' is more permissive and must be preserved for iframe/cross-origin embed flows.
|
|
101
|
+
* Max-age is always capped to 10 minutes — PKCE cookies are single-use and short-lived.
|
|
99
102
|
*/
|
|
100
103
|
export function getPKCECookieOptions(): CookieOptions;
|
|
101
104
|
export function getPKCECookieOptions(redirectUri: string | null | undefined, asString: true, expired?: boolean): string;
|
|
@@ -111,13 +114,16 @@ export function getPKCECookieOptions(
|
|
|
111
114
|
): CookieOptions | string {
|
|
112
115
|
if (asString) {
|
|
113
116
|
const options = getCookieOptions(redirectUri, true, expired);
|
|
114
|
-
return options
|
|
117
|
+
return options
|
|
118
|
+
.replace(/SameSite=Strict/i, 'SameSite=Lax')
|
|
119
|
+
.replace(/Max-Age=\d+/, `Max-Age=${expired ? 0 : PKCE_COOKIE_MAX_AGE}`);
|
|
115
120
|
}
|
|
116
121
|
|
|
117
122
|
const options = getCookieOptions(redirectUri);
|
|
118
123
|
return {
|
|
119
124
|
...options,
|
|
120
125
|
sameSite: options.sameSite.toLowerCase() === 'strict' ? 'lax' : options.sameSite,
|
|
126
|
+
maxAge: expired ? 0 : PKCE_COOKIE_MAX_AGE,
|
|
121
127
|
};
|
|
122
128
|
}
|
|
123
129
|
|
package/src/pkce.spec.ts
CHANGED
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
import { sealData } from 'iron-session';
|
|
2
|
-
import { getStateFromPKCECookieValue } from './pkce.js';
|
|
2
|
+
import { getStateFromPKCECookieValue, getPKCECookieNameForState } from './pkce.js';
|
|
3
3
|
|
|
4
4
|
const PASSWORD = process.env.WORKOS_COOKIE_PASSWORD!;
|
|
5
5
|
|
|
6
|
+
describe('getPKCECookieNameForState', () => {
|
|
7
|
+
it('should derive a cookie name prefixed with the base name', () => {
|
|
8
|
+
const state = 'any-string-at-all';
|
|
9
|
+
|
|
10
|
+
expect(getPKCECookieNameForState(state)).toMatch(/^wos-auth-verifier-[0-9a-f]{8}$/);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should produce different names for different states', () => {
|
|
14
|
+
const stateA = 'first-sealed-state-value';
|
|
15
|
+
const stateB = 'second-sealed-state-value';
|
|
16
|
+
|
|
17
|
+
expect(getPKCECookieNameForState(stateA)).not.toBe(getPKCECookieNameForState(stateB));
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should be deterministic for the same input', () => {
|
|
21
|
+
const state = 'some-sealed-state';
|
|
22
|
+
|
|
23
|
+
expect(getPKCECookieNameForState(state)).toBe(getPKCECookieNameForState(state));
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
6
27
|
describe('setPKCECookie SameSite override', () => {
|
|
7
28
|
const mockSet = vi.fn();
|
|
8
29
|
|
|
@@ -26,7 +47,7 @@ describe('setPKCECookie SameSite override', () => {
|
|
|
26
47
|
await setPKCECookie('sealed-state');
|
|
27
48
|
|
|
28
49
|
expect(mockSet).toHaveBeenCalledWith(
|
|
29
|
-
'
|
|
50
|
+
getPKCECookieNameForState('sealed-state'),
|
|
30
51
|
'sealed-state',
|
|
31
52
|
expect.objectContaining({ sameSite: 'lax' }),
|
|
32
53
|
);
|
|
@@ -40,7 +61,7 @@ describe('setPKCECookie SameSite override', () => {
|
|
|
40
61
|
await setPKCECookie('sealed-state');
|
|
41
62
|
|
|
42
63
|
expect(mockSet).toHaveBeenCalledWith(
|
|
43
|
-
'
|
|
64
|
+
getPKCECookieNameForState('sealed-state'),
|
|
44
65
|
'sealed-state',
|
|
45
66
|
expect.objectContaining({ sameSite: 'none' }),
|
|
46
67
|
);
|
|
@@ -54,7 +75,7 @@ describe('setPKCECookie SameSite override', () => {
|
|
|
54
75
|
await setPKCECookie('sealed-state');
|
|
55
76
|
|
|
56
77
|
expect(mockSet).toHaveBeenCalledWith(
|
|
57
|
-
'
|
|
78
|
+
getPKCECookieNameForState('sealed-state'),
|
|
58
79
|
'sealed-state',
|
|
59
80
|
expect.objectContaining({ sameSite: 'lax' }),
|
|
60
81
|
);
|
|
@@ -65,7 +86,7 @@ describe('setPKCECookie SameSite override', () => {
|
|
|
65
86
|
await setPKCECookie('sealed-state');
|
|
66
87
|
|
|
67
88
|
expect(mockSet).toHaveBeenCalledWith(
|
|
68
|
-
'
|
|
89
|
+
getPKCECookieNameForState('sealed-state'),
|
|
69
90
|
'sealed-state',
|
|
70
91
|
expect.objectContaining({ sameSite: 'lax' }),
|
|
71
92
|
);
|
package/src/pkce.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import fnv1a from '@sindresorhus/fnv1a';
|
|
1
2
|
import { unsealData } from 'iron-session';
|
|
2
3
|
import { cookies } from 'next/headers';
|
|
3
4
|
import * as v from 'valibot';
|
|
@@ -6,7 +7,27 @@ import { WORKOS_COOKIE_PASSWORD } from './env-variables.js';
|
|
|
6
7
|
import { State, StateSchema } from './interfaces.js';
|
|
7
8
|
|
|
8
9
|
export const PKCE_COOKIE_NAME = 'wos-auth-verifier';
|
|
9
|
-
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Short, deterministic hex fingerprint of an arbitrary string.
|
|
13
|
+
* Used to give each PKCE flow its own cookie name without depending
|
|
14
|
+
* on the internal format of the sealed state value
|
|
15
|
+
*/
|
|
16
|
+
function shortHash(input: string): string {
|
|
17
|
+
// fnv1a returns a BigInt — use 32-bit variant so it fits safely in a Number
|
|
18
|
+
const hash = Number(fnv1a(input, { size: 32 }));
|
|
19
|
+
|
|
20
|
+
// Hex-encode and pad to a fixed 8-char width
|
|
21
|
+
return hash.toString(16).padStart(8, '0');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Derive a flow-specific cookie name so concurrent auth flows don't overwrite
|
|
26
|
+
* each other's PKCE cookies. Uses an FNV-1a hash of the full sealed state
|
|
27
|
+
*/
|
|
28
|
+
export function getPKCECookieNameForState(state: string): string {
|
|
29
|
+
return `${PKCE_COOKIE_NAME}-${shortHash(state)}`;
|
|
30
|
+
}
|
|
10
31
|
|
|
11
32
|
/**
|
|
12
33
|
* Set the PKCE verifier cookie in server action context.
|
|
@@ -14,15 +35,11 @@ const PKCE_COOKIE_MAX_AGE = 600; // 10 minutes
|
|
|
14
35
|
*/
|
|
15
36
|
export async function setPKCECookie(sealedState: string): Promise<void> {
|
|
16
37
|
const nextCookies = await cookies();
|
|
17
|
-
const
|
|
38
|
+
const options = getPKCECookieOptions();
|
|
18
39
|
|
|
19
|
-
nextCookies.set(
|
|
20
|
-
|
|
21
|
-
path,
|
|
22
|
-
sameSite,
|
|
23
|
-
secure,
|
|
40
|
+
nextCookies.set(getPKCECookieNameForState(sealedState), sealedState, {
|
|
41
|
+
...options,
|
|
24
42
|
httpOnly: true,
|
|
25
|
-
maxAge: PKCE_COOKIE_MAX_AGE,
|
|
26
43
|
});
|
|
27
44
|
}
|
|
28
45
|
|
package/src/session.ts
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
Session,
|
|
19
19
|
UserInfo,
|
|
20
20
|
} from './interfaces.js';
|
|
21
|
-
import {
|
|
21
|
+
import { getPKCECookieNameForState, setPKCECookie } from './pkce.js';
|
|
22
22
|
import { getWorkOS } from './workos.js';
|
|
23
23
|
|
|
24
24
|
import type { AuthenticationResponse } from '@workos-inc/node';
|
|
@@ -26,8 +26,21 @@ import { parse, tokensToRegexp } from 'path-to-regexp';
|
|
|
26
26
|
import { handleAuthkitHeaders } from './middleware-helpers.js';
|
|
27
27
|
import { lazy, setCachePreventionHeaders } from './utils.js';
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
// Only set the PKCE cookie for initial document navigations — fetch/XHR/RSC/prefetch
|
|
30
|
+
// requests never follow cross-origin redirects so they'll never complete the OAuth
|
|
31
|
+
// flow and therefore don't need the cookie set.
|
|
32
|
+
// This prevents cookie bloat (HTTP 431) when multiple requests fire concurrently
|
|
33
|
+
// now that we are generating unique cookie names per flow, they add up quickly if
|
|
34
|
+
// we don't limit to just the initial navigation request
|
|
35
|
+
function appendPKCESetCookieHeader(request: NextRequest, headers: Headers, sealedState: string): void {
|
|
36
|
+
if (!isInitialDocumentRequest(request)) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
headers.append(
|
|
41
|
+
'Set-Cookie',
|
|
42
|
+
`${getPKCECookieNameForState(sealedState)}=${sealedState}; ${getPKCECookieOptions(request.url, true)}`,
|
|
43
|
+
);
|
|
31
44
|
}
|
|
32
45
|
|
|
33
46
|
const sessionHeaderName = 'x-workos-session';
|
|
@@ -213,7 +226,7 @@ async function updateSession(
|
|
|
213
226
|
screenHint: options.screenHint,
|
|
214
227
|
});
|
|
215
228
|
|
|
216
|
-
appendPKCESetCookieHeader(newRequestHeaders, sealedState
|
|
229
|
+
appendPKCESetCookieHeader(request, newRequestHeaders, sealedState);
|
|
217
230
|
|
|
218
231
|
return {
|
|
219
232
|
session: { user: null },
|
|
@@ -354,7 +367,7 @@ async function updateSession(
|
|
|
354
367
|
redirectUri: options.redirectUri || WORKOS_REDIRECT_URI,
|
|
355
368
|
});
|
|
356
369
|
|
|
357
|
-
appendPKCESetCookieHeader(newRequestHeaders, sealedState
|
|
370
|
+
appendPKCESetCookieHeader(request, newRequestHeaders, sealedState);
|
|
358
371
|
|
|
359
372
|
return {
|
|
360
373
|
session: { user: null },
|