@workos-inc/authkit-nextjs 2.6.0 → 2.7.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 +124 -29
- package/dist/esm/components/tokenStore.js +110 -11
- package/dist/esm/components/tokenStore.js.map +1 -1
- package/dist/esm/components/useAccessToken.js +6 -1
- package/dist/esm/components/useAccessToken.js.map +1 -1
- package/dist/esm/cookie.js +51 -0
- package/dist/esm/cookie.js.map +1 -1
- package/dist/esm/middleware.js +2 -2
- package/dist/esm/middleware.js.map +1 -1
- package/dist/esm/session.js +35 -2
- package/dist/esm/session.js.map +1 -1
- package/dist/esm/test-helpers.js +57 -0
- package/dist/esm/test-helpers.js.map +1 -0
- package/dist/esm/types/components/tokenStore.d.ts +7 -2
- package/dist/esm/types/cookie.d.ts +1 -0
- package/dist/esm/types/interfaces.d.ts +2 -0
- package/dist/esm/types/middleware.d.ts +1 -1
- package/dist/esm/types/session.d.ts +1 -1
- package/dist/esm/types/test-helpers.d.ts +3 -0
- package/dist/esm/types/workos.d.ts +1 -1
- package/dist/esm/workos.js +1 -1
- package/package.json +4 -3
- package/src/actions.spec.ts +100 -0
- package/src/auth.spec.ts +347 -0
- package/src/authkit-callback-route.spec.ts +258 -0
- package/src/components/authkit-provider.spec.tsx +471 -0
- package/src/components/button.spec.tsx +46 -0
- package/src/components/impersonation.spec.tsx +134 -0
- package/src/components/min-max-button.spec.tsx +60 -0
- package/src/components/tokenStore.spec.ts +816 -0
- package/src/components/tokenStore.ts +147 -12
- package/src/components/useAccessToken.spec.tsx +731 -0
- package/src/components/useAccessToken.ts +6 -1
- package/src/components/useTokenClaims.spec.tsx +194 -0
- package/src/cookie.spec.ts +276 -0
- package/src/cookie.ts +56 -0
- package/src/get-authorization-url.spec.ts +60 -0
- package/src/interfaces.ts +2 -0
- package/src/jwt.spec.ts +159 -0
- package/src/middleware.ts +2 -1
- package/src/session.spec.ts +1162 -0
- package/src/session.ts +41 -1
- package/src/test-helpers.ts +70 -0
- package/src/utils.spec.ts +142 -0
- package/src/workos.spec.ts +67 -0
- package/src/workos.ts +1 -1
package/src/jwt.spec.ts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { decodeJwt } from './jwt.js';
|
|
2
|
+
|
|
3
|
+
describe('decodeJwt', () => {
|
|
4
|
+
// Valid JWT token for testing (not a real token, just for testing purposes)
|
|
5
|
+
const validToken =
|
|
6
|
+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3Qta2V5In0.eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwic3ViIjoiMTIzNDU2Nzg5MCIsImF1ZCI6WyJhdWRpZW5jZTEiLCJhdWRpZW5jZTIiXSwiZXhwIjoxNzM1Njg5NjAwLCJpYXQiOjE3MzU2MDMyMDAsImp0aSI6InVuaXF1ZS1pZCIsImN1c3RvbSI6InZhbHVlIiwibmVzdGVkIjp7ImtleSI6InZhbHVlIn19.signature';
|
|
7
|
+
|
|
8
|
+
describe('valid JWT tokens', () => {
|
|
9
|
+
it('should decode a valid JWT token', () => {
|
|
10
|
+
const result = decodeJwt(validToken);
|
|
11
|
+
|
|
12
|
+
expect(result.header).toEqual({
|
|
13
|
+
alg: 'HS256',
|
|
14
|
+
typ: 'JWT',
|
|
15
|
+
kid: 'test-key',
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
expect(result.payload).toEqual({
|
|
19
|
+
iss: 'https://example.com',
|
|
20
|
+
sub: '1234567890',
|
|
21
|
+
aud: ['audience1', 'audience2'],
|
|
22
|
+
exp: 1735689600,
|
|
23
|
+
iat: 1735603200,
|
|
24
|
+
jti: 'unique-id',
|
|
25
|
+
custom: 'value',
|
|
26
|
+
nested: { key: 'value' },
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should decode a JWT with minimal header', () => {
|
|
31
|
+
const minimalToken = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMifQ.signature';
|
|
32
|
+
const result = decodeJwt(minimalToken);
|
|
33
|
+
|
|
34
|
+
expect(result.header).toEqual({
|
|
35
|
+
alg: 'HS256',
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
expect(result.payload).toEqual({
|
|
39
|
+
sub: '123',
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should decode a JWT with custom payload type', () => {
|
|
44
|
+
interface CustomPayload {
|
|
45
|
+
customField: string;
|
|
46
|
+
customNumber: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const customToken =
|
|
50
|
+
'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMiLCJjdXN0b21GaWVsZCI6InRlc3QiLCJjdXN0b21OdW1iZXIiOjQyfQ.signature';
|
|
51
|
+
const result = decodeJwt<CustomPayload>(customToken);
|
|
52
|
+
|
|
53
|
+
expect(result.payload.customField).toBe('test');
|
|
54
|
+
expect(result.payload.customNumber).toBe(42);
|
|
55
|
+
expect(result.payload.sub).toBe('123');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should handle JWT with array audience', () => {
|
|
59
|
+
const result = decodeJwt(validToken);
|
|
60
|
+
expect(result.payload.aud).toEqual(['audience1', 'audience2']);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should handle JWT with string audience', () => {
|
|
64
|
+
const singleAudToken = 'eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJzaW5nbGUtYXVkaWVuY2UifQ.signature';
|
|
65
|
+
const result = decodeJwt(singleAudToken);
|
|
66
|
+
expect(result.payload.aud).toBe('single-audience');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('invalid JWT tokens', () => {
|
|
71
|
+
it('should throw error for JWT with less than 3 parts', () => {
|
|
72
|
+
expect(() => decodeJwt('invalid.token')).toThrow('Invalid JWT format');
|
|
73
|
+
expect(() => decodeJwt('invalid')).toThrow('Invalid JWT format');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should throw error for JWT with more than 3 parts', () => {
|
|
77
|
+
expect(() => decodeJwt('too.many.parts.here')).toThrow('Invalid JWT format');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should throw error for empty string', () => {
|
|
81
|
+
expect(() => decodeJwt('')).toThrow('Invalid JWT format');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should throw error for invalid base64 in header', () => {
|
|
85
|
+
const invalidHeaderToken = 'invalid!base64.eyJzdWIiOiIxMjMifQ.signature';
|
|
86
|
+
expect(() => decodeJwt(invalidHeaderToken)).toThrow('Failed to decode JWT');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should throw error for invalid base64 in payload', () => {
|
|
90
|
+
const invalidPayloadToken = 'eyJhbGciOiJIUzI1NiJ9.invalid!base64.signature';
|
|
91
|
+
expect(() => decodeJwt(invalidPayloadToken)).toThrow('Failed to decode JWT');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should throw error for non-JSON header', () => {
|
|
95
|
+
// "not json" in base64url
|
|
96
|
+
const nonJsonHeaderToken = 'bm90IGpzb24.eyJzdWIiOiIxMjMifQ.signature';
|
|
97
|
+
expect(() => decodeJwt(nonJsonHeaderToken)).toThrow('Failed to decode JWT');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should throw error for non-JSON payload', () => {
|
|
101
|
+
// "not json" in base64url
|
|
102
|
+
const nonJsonPayloadToken = 'eyJhbGciOiJIUzI1NiJ9.bm90IGpzb24.signature';
|
|
103
|
+
expect(() => decodeJwt(nonJsonPayloadToken)).toThrow('Failed to decode JWT');
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('edge cases', () => {
|
|
108
|
+
it('should handle empty header object', () => {
|
|
109
|
+
const emptyHeaderToken = 'e30.eyJzdWIiOiIxMjMifQ.signature';
|
|
110
|
+
const result = decodeJwt(emptyHeaderToken);
|
|
111
|
+
expect(result.header).toEqual({});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should handle empty payload object', () => {
|
|
115
|
+
const emptyPayloadToken = 'eyJhbGciOiJIUzI1NiJ9.e30.signature';
|
|
116
|
+
const result = decodeJwt(emptyPayloadToken);
|
|
117
|
+
expect(result.payload).toEqual({});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('should handle JWT with null values', () => {
|
|
121
|
+
const nullValueToken = 'eyJhbGciOm51bGx9.eyJzdWIiOm51bGwsImRhdGEiOm51bGx9.signature';
|
|
122
|
+
const result = decodeJwt(nullValueToken);
|
|
123
|
+
expect(result.header.alg).toBeNull();
|
|
124
|
+
expect(result.payload.sub).toBeNull();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should handle JWT with nested objects', () => {
|
|
128
|
+
const nestedToken = 'eyJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7Im5lc3RlZCI6eyJkZWVwIjoidmFsdWUifX19.signature';
|
|
129
|
+
const result = decodeJwt(nestedToken);
|
|
130
|
+
expect(result.payload).toEqual({
|
|
131
|
+
data: {
|
|
132
|
+
nested: {
|
|
133
|
+
deep: 'value',
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should handle JWT with arrays in payload', () => {
|
|
140
|
+
const arrayToken =
|
|
141
|
+
'eyJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJhZG1pbiIsInVzZXIiXSwic2NvcGVzIjpbInJlYWQiLCJ3cml0ZSJdfQ.signature';
|
|
142
|
+
const result = decodeJwt(arrayToken);
|
|
143
|
+
expect(result.payload).toEqual({
|
|
144
|
+
roles: ['admin', 'user'],
|
|
145
|
+
scopes: ['read', 'write'],
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('should handle JWT with numeric values', () => {
|
|
150
|
+
const numericToken = 'eyJhbGciOiJIUzI1NiJ9.eyJjb3VudCI6NDIsInJhdGlvIjozLjE0LCJhY3RpdmUiOnRydWV9.signature';
|
|
151
|
+
const result = decodeJwt(numericToken);
|
|
152
|
+
expect(result.payload).toEqual({
|
|
153
|
+
count: 42,
|
|
154
|
+
ratio: 3.14,
|
|
155
|
+
active: true,
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
package/src/middleware.ts
CHANGED
|
@@ -8,9 +8,10 @@ export function authkitMiddleware({
|
|
|
8
8
|
middlewareAuth = { enabled: false, unauthenticatedPaths: [] },
|
|
9
9
|
redirectUri = WORKOS_REDIRECT_URI,
|
|
10
10
|
signUpPaths = [],
|
|
11
|
+
eagerAuth = false,
|
|
11
12
|
}: AuthkitMiddlewareOptions = {}): NextMiddleware {
|
|
12
13
|
return function (request) {
|
|
13
|
-
return updateSessionMiddleware(request, debug, middlewareAuth, redirectUri, signUpPaths);
|
|
14
|
+
return updateSessionMiddleware(request, debug, middlewareAuth, redirectUri, signUpPaths, eagerAuth);
|
|
14
15
|
};
|
|
15
16
|
}
|
|
16
17
|
|