@workos-inc/authkit-nextjs 2.16.1 → 2.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/env-variables.js +2 -1
- package/dist/esm/env-variables.js.map +1 -1
- package/dist/esm/get-authorization-url.js +27 -1
- package/dist/esm/get-authorization-url.js.map +1 -1
- package/dist/esm/types/env-variables.d.ts +2 -1
- package/package.json +2 -2
- package/src/env-variables.ts +2 -0
- package/src/get-authorization-url.spec.ts +111 -0
- package/src/get-authorization-url.ts +39 -1
|
@@ -11,11 +11,12 @@ const WORKOS_COOKIE_DOMAIN = getEnvVariable('WORKOS_COOKIE_DOMAIN');
|
|
|
11
11
|
const WORKOS_COOKIE_MAX_AGE = getEnvVariable('WORKOS_COOKIE_MAX_AGE');
|
|
12
12
|
const WORKOS_COOKIE_NAME = getEnvVariable('WORKOS_COOKIE_NAME');
|
|
13
13
|
const WORKOS_COOKIE_SAMESITE = getEnvVariable('WORKOS_COOKIE_SAMESITE');
|
|
14
|
+
const WORKOS_CLAIM_TOKEN = getEnvVariable('WORKOS_CLAIM_TOKEN');
|
|
14
15
|
const WORKOS_ENABLE_PKCE = getEnvVariable('WORKOS_ENABLE_PKCE');
|
|
15
16
|
// Required env variables
|
|
16
17
|
const WORKOS_API_KEY = (_a = getEnvVariable('WORKOS_API_KEY')) !== null && _a !== void 0 ? _a : '';
|
|
17
18
|
const WORKOS_CLIENT_ID = (_b = getEnvVariable('WORKOS_CLIENT_ID')) !== null && _b !== void 0 ? _b : '';
|
|
18
19
|
const WORKOS_COOKIE_PASSWORD = (_c = getEnvVariable('WORKOS_COOKIE_PASSWORD')) !== null && _c !== void 0 ? _c : '';
|
|
19
20
|
const WORKOS_REDIRECT_URI = (_d = process.env.NEXT_PUBLIC_WORKOS_REDIRECT_URI) !== null && _d !== void 0 ? _d : '';
|
|
20
|
-
export { WORKOS_API_HOSTNAME, WORKOS_API_HTTPS, WORKOS_API_KEY, WORKOS_API_PORT, WORKOS_CLIENT_ID, WORKOS_COOKIE_DOMAIN, WORKOS_COOKIE_MAX_AGE, WORKOS_COOKIE_NAME, WORKOS_COOKIE_PASSWORD, WORKOS_REDIRECT_URI, WORKOS_COOKIE_SAMESITE, WORKOS_ENABLE_PKCE, };
|
|
21
|
+
export { WORKOS_API_HOSTNAME, WORKOS_API_HTTPS, WORKOS_API_KEY, WORKOS_API_PORT, WORKOS_CLAIM_TOKEN, WORKOS_CLIENT_ID, WORKOS_COOKIE_DOMAIN, WORKOS_COOKIE_MAX_AGE, WORKOS_COOKIE_NAME, WORKOS_COOKIE_PASSWORD, WORKOS_REDIRECT_URI, WORKOS_COOKIE_SAMESITE, WORKOS_ENABLE_PKCE, };
|
|
21
22
|
//# sourceMappingURL=env-variables.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env-variables.js","sourceRoot":"","sources":["../../src/env-variables.ts"],"names":[],"mappings":"AAAA,0BAA0B;;AAE1B,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,yBAAyB;AACzB,MAAM,mBAAmB,GAAG,cAAc,CAAC,qBAAqB,CAAC,CAAC;AAClE,MAAM,gBAAgB,GAAG,cAAc,CAAC,kBAAkB,CAAC,CAAC;AAC5D,MAAM,eAAe,GAAG,cAAc,CAAC,iBAAiB,CAAC,CAAC;AAC1D,MAAM,oBAAoB,GAAG,cAAc,CAAC,sBAAsB,CAAC,CAAC;AACpE,MAAM,qBAAqB,GAAG,cAAc,CAAC,uBAAuB,CAAC,CAAC;AACtE,MAAM,kBAAkB,GAAG,cAAc,CAAC,oBAAoB,CAAC,CAAC;AAChE,MAAM,sBAAsB,GAAG,cAAc,CAAC,wBAAwB,CAA0C,CAAC;AACjH,MAAM,kBAAkB,GAAG,cAAc,CAAC,oBAAoB,CAAC,CAAC;AAEhE,yBAAyB;AACzB,MAAM,cAAc,GAAG,MAAA,cAAc,CAAC,gBAAgB,CAAC,mCAAI,EAAE,CAAC;AAC9D,MAAM,gBAAgB,GAAG,MAAA,cAAc,CAAC,kBAAkB,CAAC,mCAAI,EAAE,CAAC;AAClE,MAAM,sBAAsB,GAAG,MAAA,cAAc,CAAC,wBAAwB,CAAC,mCAAI,EAAE,CAAC;AAC9E,MAAM,mBAAmB,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,+BAA+B,mCAAI,EAAE,CAAC;AAE9E,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,GACnB,CAAC"}
|
|
1
|
+
{"version":3,"file":"env-variables.js","sourceRoot":"","sources":["../../src/env-variables.ts"],"names":[],"mappings":"AAAA,0BAA0B;;AAE1B,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,yBAAyB;AACzB,MAAM,mBAAmB,GAAG,cAAc,CAAC,qBAAqB,CAAC,CAAC;AAClE,MAAM,gBAAgB,GAAG,cAAc,CAAC,kBAAkB,CAAC,CAAC;AAC5D,MAAM,eAAe,GAAG,cAAc,CAAC,iBAAiB,CAAC,CAAC;AAC1D,MAAM,oBAAoB,GAAG,cAAc,CAAC,sBAAsB,CAAC,CAAC;AACpE,MAAM,qBAAqB,GAAG,cAAc,CAAC,uBAAuB,CAAC,CAAC;AACtE,MAAM,kBAAkB,GAAG,cAAc,CAAC,oBAAoB,CAAC,CAAC;AAChE,MAAM,sBAAsB,GAAG,cAAc,CAAC,wBAAwB,CAA0C,CAAC;AACjH,MAAM,kBAAkB,GAAG,cAAc,CAAC,oBAAoB,CAAC,CAAC;AAChE,MAAM,kBAAkB,GAAG,cAAc,CAAC,oBAAoB,CAAC,CAAC;AAEhE,yBAAyB;AACzB,MAAM,cAAc,GAAG,MAAA,cAAc,CAAC,gBAAgB,CAAC,mCAAI,EAAE,CAAC;AAC9D,MAAM,gBAAgB,GAAG,MAAA,cAAc,CAAC,kBAAkB,CAAC,mCAAI,EAAE,CAAC;AAClE,MAAM,sBAAsB,GAAG,MAAA,cAAc,CAAC,wBAAwB,CAAC,mCAAI,EAAE,CAAC;AAC9E,MAAM,mBAAmB,GAAG,MAAA,OAAO,CAAC,GAAG,CAAC,+BAA+B,mCAAI,EAAE,CAAC;AAE9E,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,GACnB,CAAC"}
|
|
@@ -1,7 +1,31 @@
|
|
|
1
1
|
import { sealData } from 'iron-session';
|
|
2
2
|
import { headers } from 'next/headers';
|
|
3
|
-
import { WORKOS_CLIENT_ID, WORKOS_COOKIE_PASSWORD, WORKOS_ENABLE_PKCE, WORKOS_REDIRECT_URI } from './env-variables.js';
|
|
3
|
+
import { WORKOS_CLAIM_TOKEN, WORKOS_CLIENT_ID, WORKOS_COOKIE_PASSWORD, WORKOS_ENABLE_PKCE, WORKOS_REDIRECT_URI, } from './env-variables.js';
|
|
4
4
|
import { getWorkOS } from './workos.js';
|
|
5
|
+
async function fetchClaimNonce(baseURL) {
|
|
6
|
+
try {
|
|
7
|
+
const response = await fetch(`${baseURL}/x/one-shot-environments/claim-nonces`, {
|
|
8
|
+
method: 'POST',
|
|
9
|
+
headers: { 'Content-Type': 'application/json' },
|
|
10
|
+
body: JSON.stringify({
|
|
11
|
+
client_id: WORKOS_CLIENT_ID,
|
|
12
|
+
claim_token: WORKOS_CLAIM_TOKEN,
|
|
13
|
+
}),
|
|
14
|
+
});
|
|
15
|
+
if (!response.ok) {
|
|
16
|
+
if (response.status !== 409) {
|
|
17
|
+
console.warn(`[authkit-nextjs]: Failed to exchange WORKOS_CLAIM_TOKEN (${response.status}). Try removing WORKOS_CLAIM_TOKEN from your environment variables.`);
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const data = await response.json();
|
|
22
|
+
return data.nonce;
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
console.warn('[authkit-nextjs]: Failed to exchange WORKOS_CLAIM_TOKEN. Try removing WORKOS_CLAIM_TOKEN from your environment variables.', error);
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
5
29
|
async function getAuthorizationUrl(options = {}) {
|
|
6
30
|
var _a;
|
|
7
31
|
const { returnPathname, screenHint, organizationId, loginHint, prompt, state: customState } = options;
|
|
@@ -13,6 +37,7 @@ async function getAuthorizationUrl(options = {}) {
|
|
|
13
37
|
const internalState = returnPathname
|
|
14
38
|
? btoa(JSON.stringify({ returnPathname })).replace(/\+/g, '-').replace(/\//g, '_')
|
|
15
39
|
: null;
|
|
40
|
+
const claimNonce = WORKOS_CLAIM_TOKEN ? await fetchClaimNonce(getWorkOS().baseURL) : null;
|
|
16
41
|
const finalState = internalState && customState ? `${internalState}.${customState}` : internalState || customState || undefined;
|
|
17
42
|
const baseOptions = {
|
|
18
43
|
provider: 'authkit',
|
|
@@ -23,6 +48,7 @@ async function getAuthorizationUrl(options = {}) {
|
|
|
23
48
|
organizationId,
|
|
24
49
|
loginHint,
|
|
25
50
|
prompt,
|
|
51
|
+
...(claimNonce && { claimNonce }),
|
|
26
52
|
};
|
|
27
53
|
if (WORKOS_ENABLE_PKCE === 'true') {
|
|
28
54
|
const pkce = await getWorkOS().pkce.generate();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-authorization-url.js","sourceRoot":"","sources":["../../src/get-authorization-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,
|
|
1
|
+
{"version":3,"file":"get-authorization-url.js","sourceRoot":"","sources":["../../src/get-authorization-url.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,9 +5,10 @@ declare const WORKOS_COOKIE_DOMAIN: string | undefined;
|
|
|
5
5
|
declare const WORKOS_COOKIE_MAX_AGE: string | undefined;
|
|
6
6
|
declare const WORKOS_COOKIE_NAME: string | undefined;
|
|
7
7
|
declare const WORKOS_COOKIE_SAMESITE: "lax" | "strict" | "none" | undefined;
|
|
8
|
+
declare const WORKOS_CLAIM_TOKEN: string | undefined;
|
|
8
9
|
declare const WORKOS_ENABLE_PKCE: string | undefined;
|
|
9
10
|
declare const WORKOS_API_KEY: string;
|
|
10
11
|
declare const WORKOS_CLIENT_ID: string;
|
|
11
12
|
declare const WORKOS_COOKIE_PASSWORD: string;
|
|
12
13
|
declare const WORKOS_REDIRECT_URI: string;
|
|
13
|
-
export { WORKOS_API_HOSTNAME, WORKOS_API_HTTPS, WORKOS_API_KEY, WORKOS_API_PORT, WORKOS_CLIENT_ID, WORKOS_COOKIE_DOMAIN, WORKOS_COOKIE_MAX_AGE, WORKOS_COOKIE_NAME, WORKOS_COOKIE_PASSWORD, WORKOS_REDIRECT_URI, WORKOS_COOKIE_SAMESITE, WORKOS_ENABLE_PKCE, };
|
|
14
|
+
export { WORKOS_API_HOSTNAME, WORKOS_API_HTTPS, WORKOS_API_KEY, WORKOS_API_PORT, WORKOS_CLAIM_TOKEN, WORKOS_CLIENT_ID, WORKOS_COOKIE_DOMAIN, WORKOS_COOKIE_MAX_AGE, WORKOS_COOKIE_NAME, WORKOS_COOKIE_PASSWORD, WORKOS_REDIRECT_URI, WORKOS_COOKIE_SAMESITE, WORKOS_ENABLE_PKCE, };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workos-inc/authkit-nextjs",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.17.0",
|
|
4
4
|
"description": "Authentication and session helpers for using WorkOS & AuthKit with Next.js",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@workos-inc/node": "^8.
|
|
26
|
+
"@workos-inc/node": "^8.9.0",
|
|
27
27
|
"iron-session": "^8.0.4",
|
|
28
28
|
"jose": "^5.10.0",
|
|
29
29
|
"path-to-regexp": "^6.3.0"
|
package/src/env-variables.ts
CHANGED
|
@@ -12,6 +12,7 @@ const WORKOS_COOKIE_DOMAIN = getEnvVariable('WORKOS_COOKIE_DOMAIN');
|
|
|
12
12
|
const WORKOS_COOKIE_MAX_AGE = getEnvVariable('WORKOS_COOKIE_MAX_AGE');
|
|
13
13
|
const WORKOS_COOKIE_NAME = getEnvVariable('WORKOS_COOKIE_NAME');
|
|
14
14
|
const WORKOS_COOKIE_SAMESITE = getEnvVariable('WORKOS_COOKIE_SAMESITE') as 'lax' | 'strict' | 'none' | undefined;
|
|
15
|
+
const WORKOS_CLAIM_TOKEN = getEnvVariable('WORKOS_CLAIM_TOKEN');
|
|
15
16
|
const WORKOS_ENABLE_PKCE = getEnvVariable('WORKOS_ENABLE_PKCE');
|
|
16
17
|
|
|
17
18
|
// Required env variables
|
|
@@ -25,6 +26,7 @@ export {
|
|
|
25
26
|
WORKOS_API_HTTPS,
|
|
26
27
|
WORKOS_API_KEY,
|
|
27
28
|
WORKOS_API_PORT,
|
|
29
|
+
WORKOS_CLAIM_TOKEN,
|
|
28
30
|
WORKOS_CLIENT_ID,
|
|
29
31
|
WORKOS_COOKIE_DOMAIN,
|
|
30
32
|
WORKOS_COOKIE_MAX_AGE,
|
|
@@ -5,6 +5,7 @@ import { getWorkOS } from './workos.js';
|
|
|
5
5
|
// Mock dependencies
|
|
6
6
|
const { fakeWorkosInstance } = vi.hoisted(() => ({
|
|
7
7
|
fakeWorkosInstance: {
|
|
8
|
+
baseURL: 'https://api.workos.com',
|
|
8
9
|
userManagement: {
|
|
9
10
|
getAuthorizationUrl: vi.fn(),
|
|
10
11
|
},
|
|
@@ -70,6 +71,116 @@ describe('getAuthorizationUrl', () => {
|
|
|
70
71
|
);
|
|
71
72
|
});
|
|
72
73
|
|
|
74
|
+
describe('claim nonce', () => {
|
|
75
|
+
afterEach(() => {
|
|
76
|
+
delete process.env.WORKOS_CLAIM_TOKEN;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('does not fetch nonce when WORKOS_CLAIM_TOKEN is not set', async () => {
|
|
80
|
+
const fetchSpy = vi.spyOn(globalThis, 'fetch');
|
|
81
|
+
vi.mocked(workos.userManagement.getAuthorizationUrl).mockReturnValue('mock-url');
|
|
82
|
+
|
|
83
|
+
await getAuthorizationUrl({});
|
|
84
|
+
|
|
85
|
+
expect(fetchSpy).not.toHaveBeenCalledWith(expect.stringContaining('claim-nonces'), expect.anything());
|
|
86
|
+
expect(workos.userManagement.getAuthorizationUrl).toHaveBeenCalledWith(
|
|
87
|
+
expect.not.objectContaining({ claimNonce: expect.any(String) }),
|
|
88
|
+
);
|
|
89
|
+
fetchSpy.mockRestore();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('fetches nonce and passes claimNonce when WORKOS_CLAIM_TOKEN is set', async () => {
|
|
93
|
+
process.env.WORKOS_CLAIM_TOKEN = 'test-claim-token';
|
|
94
|
+
const fetchSpy = vi
|
|
95
|
+
.spyOn(globalThis, 'fetch')
|
|
96
|
+
.mockResolvedValueOnce(new Response(JSON.stringify({ nonce: 'test-nonce' }), { status: 201 }));
|
|
97
|
+
|
|
98
|
+
vi.resetModules();
|
|
99
|
+
const { getAuthorizationUrl: freshGetAuthorizationUrl } = await import('./get-authorization-url.js');
|
|
100
|
+
vi.mocked(workos.userManagement.getAuthorizationUrl).mockReturnValue('mock-url');
|
|
101
|
+
|
|
102
|
+
await freshGetAuthorizationUrl({});
|
|
103
|
+
|
|
104
|
+
expect(fetchSpy).toHaveBeenCalledWith(
|
|
105
|
+
'https://api.workos.com/x/one-shot-environments/claim-nonces',
|
|
106
|
+
expect.objectContaining({
|
|
107
|
+
method: 'POST',
|
|
108
|
+
headers: { 'Content-Type': 'application/json' },
|
|
109
|
+
body: JSON.stringify({ client_id: 'client_1234567890', claim_token: 'test-claim-token' }),
|
|
110
|
+
}),
|
|
111
|
+
);
|
|
112
|
+
expect(workos.userManagement.getAuthorizationUrl).toHaveBeenCalledWith(
|
|
113
|
+
expect.objectContaining({ claimNonce: 'test-nonce' }),
|
|
114
|
+
);
|
|
115
|
+
fetchSpy.mockRestore();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('proceeds without nonce on network error', async () => {
|
|
119
|
+
process.env.WORKOS_CLAIM_TOKEN = 'test-claim-token';
|
|
120
|
+
const fetchSpy = vi.spyOn(globalThis, 'fetch').mockRejectedValueOnce(new Error('Network error'));
|
|
121
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
122
|
+
|
|
123
|
+
vi.resetModules();
|
|
124
|
+
const { getAuthorizationUrl: freshGetAuthorizationUrl } = await import('./get-authorization-url.js');
|
|
125
|
+
vi.mocked(workos.userManagement.getAuthorizationUrl).mockReturnValue('mock-url');
|
|
126
|
+
|
|
127
|
+
await freshGetAuthorizationUrl({});
|
|
128
|
+
|
|
129
|
+
expect(workos.userManagement.getAuthorizationUrl).toHaveBeenCalledWith(
|
|
130
|
+
expect.not.objectContaining({ claimNonce: expect.any(String) }),
|
|
131
|
+
);
|
|
132
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
133
|
+
'[authkit-nextjs]: Failed to exchange WORKOS_CLAIM_TOKEN. Try removing WORKOS_CLAIM_TOKEN from your environment variables.',
|
|
134
|
+
expect.any(Error),
|
|
135
|
+
);
|
|
136
|
+
fetchSpy.mockRestore();
|
|
137
|
+
warnSpy.mockRestore();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('proceeds without nonce on non-OK response', async () => {
|
|
141
|
+
process.env.WORKOS_CLAIM_TOKEN = 'test-claim-token';
|
|
142
|
+
const fetchSpy = vi
|
|
143
|
+
.spyOn(globalThis, 'fetch')
|
|
144
|
+
.mockResolvedValueOnce(new Response('Unauthorized', { status: 401 }));
|
|
145
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
146
|
+
|
|
147
|
+
vi.resetModules();
|
|
148
|
+
const { getAuthorizationUrl: freshGetAuthorizationUrl } = await import('./get-authorization-url.js');
|
|
149
|
+
vi.mocked(workos.userManagement.getAuthorizationUrl).mockReturnValue('mock-url');
|
|
150
|
+
|
|
151
|
+
await freshGetAuthorizationUrl({});
|
|
152
|
+
|
|
153
|
+
expect(workos.userManagement.getAuthorizationUrl).toHaveBeenCalledWith(
|
|
154
|
+
expect.not.objectContaining({ claimNonce: expect.any(String) }),
|
|
155
|
+
);
|
|
156
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
157
|
+
'[authkit-nextjs]: Failed to exchange WORKOS_CLAIM_TOKEN (401). Try removing WORKOS_CLAIM_TOKEN from your environment variables.',
|
|
158
|
+
);
|
|
159
|
+
fetchSpy.mockRestore();
|
|
160
|
+
warnSpy.mockRestore();
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('works with PKCE disabled', async () => {
|
|
164
|
+
process.env.WORKOS_CLAIM_TOKEN = 'test-claim-token';
|
|
165
|
+
process.env.WORKOS_DISABLE_PKCE = 'true';
|
|
166
|
+
const fetchSpy = vi
|
|
167
|
+
.spyOn(globalThis, 'fetch')
|
|
168
|
+
.mockResolvedValueOnce(new Response(JSON.stringify({ nonce: 'test-nonce' }), { status: 201 }));
|
|
169
|
+
|
|
170
|
+
vi.resetModules();
|
|
171
|
+
const { getAuthorizationUrl: freshGetAuthorizationUrl } = await import('./get-authorization-url.js');
|
|
172
|
+
vi.mocked(workos.userManagement.getAuthorizationUrl).mockReturnValue('mock-url');
|
|
173
|
+
|
|
174
|
+
const result = await freshGetAuthorizationUrl({});
|
|
175
|
+
|
|
176
|
+
expect(workos.userManagement.getAuthorizationUrl).toHaveBeenCalledWith(
|
|
177
|
+
expect.objectContaining({ claimNonce: 'test-nonce' }),
|
|
178
|
+
);
|
|
179
|
+
expect(result.pkceCookieValue).toBeUndefined();
|
|
180
|
+
fetchSpy.mockRestore();
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
73
184
|
describe('PKCE', () => {
|
|
74
185
|
it('skips PKCE by default', async () => {
|
|
75
186
|
vi.mocked(workos.userManagement.getAuthorizationUrl).mockReturnValue('mock-url');
|
|
@@ -1,9 +1,44 @@
|
|
|
1
1
|
import { sealData } from 'iron-session';
|
|
2
2
|
import { headers } from 'next/headers';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
WORKOS_CLAIM_TOKEN,
|
|
5
|
+
WORKOS_CLIENT_ID,
|
|
6
|
+
WORKOS_COOKIE_PASSWORD,
|
|
7
|
+
WORKOS_ENABLE_PKCE,
|
|
8
|
+
WORKOS_REDIRECT_URI,
|
|
9
|
+
} from './env-variables.js';
|
|
4
10
|
import { GetAuthURLOptions, GetAuthURLResult } from './interfaces.js';
|
|
5
11
|
import { getWorkOS } from './workos.js';
|
|
6
12
|
|
|
13
|
+
async function fetchClaimNonce(baseURL: string): Promise<string | null> {
|
|
14
|
+
try {
|
|
15
|
+
const response = await fetch(`${baseURL}/x/one-shot-environments/claim-nonces`, {
|
|
16
|
+
method: 'POST',
|
|
17
|
+
headers: { 'Content-Type': 'application/json' },
|
|
18
|
+
body: JSON.stringify({
|
|
19
|
+
client_id: WORKOS_CLIENT_ID,
|
|
20
|
+
claim_token: WORKOS_CLAIM_TOKEN,
|
|
21
|
+
}),
|
|
22
|
+
});
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
if (response.status !== 409) {
|
|
25
|
+
console.warn(
|
|
26
|
+
`[authkit-nextjs]: Failed to exchange WORKOS_CLAIM_TOKEN (${response.status}). Try removing WORKOS_CLAIM_TOKEN from your environment variables.`,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const data = await response.json();
|
|
32
|
+
return data.nonce;
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.warn(
|
|
35
|
+
'[authkit-nextjs]: Failed to exchange WORKOS_CLAIM_TOKEN. Try removing WORKOS_CLAIM_TOKEN from your environment variables.',
|
|
36
|
+
error,
|
|
37
|
+
);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
7
42
|
async function getAuthorizationUrl(options: GetAuthURLOptions = {}): Promise<GetAuthURLResult> {
|
|
8
43
|
const { returnPathname, screenHint, organizationId, loginHint, prompt, state: customState } = options;
|
|
9
44
|
let redirectUri = options.redirectUri;
|
|
@@ -16,6 +51,8 @@ async function getAuthorizationUrl(options: GetAuthURLOptions = {}): Promise<Get
|
|
|
16
51
|
? btoa(JSON.stringify({ returnPathname })).replace(/\+/g, '-').replace(/\//g, '_')
|
|
17
52
|
: null;
|
|
18
53
|
|
|
54
|
+
const claimNonce = WORKOS_CLAIM_TOKEN ? await fetchClaimNonce(getWorkOS().baseURL) : null;
|
|
55
|
+
|
|
19
56
|
const finalState =
|
|
20
57
|
internalState && customState ? `${internalState}.${customState}` : internalState || customState || undefined;
|
|
21
58
|
|
|
@@ -28,6 +65,7 @@ async function getAuthorizationUrl(options: GetAuthURLOptions = {}): Promise<Get
|
|
|
28
65
|
organizationId,
|
|
29
66
|
loginHint,
|
|
30
67
|
prompt,
|
|
68
|
+
...(claimNonce && { claimNonce }),
|
|
31
69
|
};
|
|
32
70
|
|
|
33
71
|
if (WORKOS_ENABLE_PKCE === 'true') {
|