@workos-inc/authkit-nextjs 2.10.0 → 2.11.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 +93 -39
- package/dist/esm/auth.js +9 -1
- package/dist/esm/auth.js.map +1 -1
- package/dist/esm/authkit-callback-route.js +15 -6
- package/dist/esm/authkit-callback-route.js.map +1 -1
- package/dist/esm/components/impersonation.js +8 -6
- package/dist/esm/components/impersonation.js.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/session.js +56 -2
- package/dist/esm/session.js.map +1 -1
- package/dist/esm/test-helpers.js +1 -0
- package/dist/esm/test-helpers.js.map +1 -1
- package/dist/esm/types/components/impersonation.d.ts +2 -1
- package/dist/esm/types/index.d.ts +2 -1
- package/dist/esm/types/utils.d.ts +5 -0
- package/dist/esm/types/validate-api-key.d.ts +1 -0
- package/dist/esm/types/workos.d.ts +1 -1
- package/dist/esm/utils.js +10 -0
- package/dist/esm/utils.js.map +1 -1
- package/dist/esm/validate-api-key.js +17 -0
- package/dist/esm/validate-api-key.js.map +1 -0
- package/dist/esm/workos.js +1 -1
- package/package.json +4 -4
- package/src/auth.ts +11 -1
- package/src/authkit-callback-route.spec.ts +1 -0
- package/src/authkit-callback-route.ts +17 -6
- package/src/components/impersonation.spec.tsx +136 -20
- package/src/components/impersonation.tsx +8 -6
- package/src/index.ts +2 -0
- package/src/session.spec.ts +2 -4
- package/src/session.ts +73 -2
- package/src/test-helpers.ts +1 -0
- package/src/utils.ts +11 -0
- package/src/validate-api-key.spec.ts +113 -0
- package/src/validate-api-key.ts +19 -0
- package/src/workos.ts +1 -1
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
|
|
2
|
+
|
|
3
|
+
import { validateApiKey } from './validate-api-key.js';
|
|
4
|
+
import { getWorkOS } from './workos.js';
|
|
5
|
+
|
|
6
|
+
// These are mocked in jest.setup.ts
|
|
7
|
+
import { headers } from 'next/headers';
|
|
8
|
+
|
|
9
|
+
const workos = getWorkOS();
|
|
10
|
+
|
|
11
|
+
describe('validate-api-key.ts', () => {
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
// Clear all mocks between tests
|
|
14
|
+
jest.clearAllMocks();
|
|
15
|
+
|
|
16
|
+
const nextHeaders = await headers();
|
|
17
|
+
// @ts-expect-error - _reset is part of the mock
|
|
18
|
+
nextHeaders._reset();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('validateApiKey', () => {
|
|
22
|
+
it('should return valid API key when Bearer token is present and valid', async () => {
|
|
23
|
+
const mockApiKeyResponse = {
|
|
24
|
+
apiKey: {
|
|
25
|
+
id: 'api_key_123',
|
|
26
|
+
object: 'api_key' as const,
|
|
27
|
+
name: 'Test API Key',
|
|
28
|
+
obfuscatedValue: 'sk_…7890',
|
|
29
|
+
createdAt: '2024-01-01T00:00:00Z',
|
|
30
|
+
updatedAt: '2024-01-01T00:00:00Z',
|
|
31
|
+
lastUsedAt: '2024-01-01T00:00:00Z',
|
|
32
|
+
permissions: [],
|
|
33
|
+
owner: { type: 'organization' as const, id: 'org_123' },
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
jest.spyOn(workos.apiKeys, 'validateApiKey').mockResolvedValue(mockApiKeyResponse);
|
|
38
|
+
|
|
39
|
+
const nextHeaders = await headers();
|
|
40
|
+
nextHeaders.set('authorization', 'Bearer sk_test_1234567890');
|
|
41
|
+
|
|
42
|
+
const result = await validateApiKey();
|
|
43
|
+
|
|
44
|
+
expect(workos.apiKeys.validateApiKey).toHaveBeenCalledWith({
|
|
45
|
+
value: 'sk_test_1234567890',
|
|
46
|
+
});
|
|
47
|
+
expect(result).toEqual(mockApiKeyResponse);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should return { apiKey: null } when no authorization header is present', async () => {
|
|
51
|
+
// Don't set any authorization header
|
|
52
|
+
const result = await validateApiKey();
|
|
53
|
+
|
|
54
|
+
expect(workos.apiKeys.validateApiKey).not.toHaveBeenCalled();
|
|
55
|
+
expect(result).toEqual({ apiKey: null });
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should return { apiKey: null } when authorization header is empty', async () => {
|
|
59
|
+
const nextHeaders = await headers();
|
|
60
|
+
nextHeaders.set('authorization', '');
|
|
61
|
+
|
|
62
|
+
const result = await validateApiKey();
|
|
63
|
+
|
|
64
|
+
expect(workos.apiKeys.validateApiKey).not.toHaveBeenCalled();
|
|
65
|
+
expect(result).toEqual({ apiKey: null });
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should return { apiKey: null } when authorization header does not start with Bearer', async () => {
|
|
69
|
+
const nextHeaders = await headers();
|
|
70
|
+
nextHeaders.set('authorization', 'Basic dXNlcjpwYXNz');
|
|
71
|
+
|
|
72
|
+
const result = await validateApiKey();
|
|
73
|
+
|
|
74
|
+
expect(workos.apiKeys.validateApiKey).not.toHaveBeenCalled();
|
|
75
|
+
expect(result).toEqual({ apiKey: null });
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should return { apiKey: null } when Bearer token is missing', async () => {
|
|
79
|
+
const nextHeaders = await headers();
|
|
80
|
+
nextHeaders.set('authorization', 'Bearer');
|
|
81
|
+
|
|
82
|
+
const result = await validateApiKey();
|
|
83
|
+
|
|
84
|
+
expect(workos.apiKeys.validateApiKey).not.toHaveBeenCalled();
|
|
85
|
+
expect(result).toEqual({ apiKey: null });
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should return { apiKey: null } when Bearer token is only whitespace', async () => {
|
|
89
|
+
const nextHeaders = await headers();
|
|
90
|
+
nextHeaders.set('authorization', 'Bearer ');
|
|
91
|
+
|
|
92
|
+
const result = await validateApiKey();
|
|
93
|
+
|
|
94
|
+
expect(workos.apiKeys.validateApiKey).not.toHaveBeenCalled();
|
|
95
|
+
expect(result).toEqual({ apiKey: null });
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should return { apiKey: null } when WorkOS validation fails', async () => {
|
|
99
|
+
const mockResponse = { apiKey: null };
|
|
100
|
+
jest.spyOn(workos.apiKeys, 'validateApiKey').mockResolvedValue(mockResponse);
|
|
101
|
+
|
|
102
|
+
const nextHeaders = await headers();
|
|
103
|
+
nextHeaders.set('authorization', 'Bearer invalid_key');
|
|
104
|
+
|
|
105
|
+
const result = await validateApiKey();
|
|
106
|
+
|
|
107
|
+
expect(workos.apiKeys.validateApiKey).toHaveBeenCalledWith({
|
|
108
|
+
value: 'invalid_key',
|
|
109
|
+
});
|
|
110
|
+
expect(result).toEqual({ apiKey: null });
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { getWorkOS } from './workos.js';
|
|
4
|
+
import { headers } from 'next/headers';
|
|
5
|
+
|
|
6
|
+
export async function validateApiKey() {
|
|
7
|
+
const headersList = await headers();
|
|
8
|
+
const authorizationHeader = headersList.get('authorization');
|
|
9
|
+
if (!authorizationHeader) {
|
|
10
|
+
return { apiKey: null };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const value = authorizationHeader.match(/Bearer\s+(.*)/i)?.[1];
|
|
14
|
+
if (!value) {
|
|
15
|
+
return { apiKey: null };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return getWorkOS().apiKeys.validateApiKey({ value });
|
|
19
|
+
}
|
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.
|
|
5
|
+
export const VERSION = '2.11.1';
|
|
6
6
|
|
|
7
7
|
const options = {
|
|
8
8
|
apiHostname: WORKOS_API_HOSTNAME,
|