bezzie 0.1.4 → 0.1.6
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/adapters/cloudflare-kv.d.ts +10 -0
- package/dist/adapters/cloudflare-kv.d.ts.map +1 -0
- package/dist/{src/adapters → adapters}/cloudflare-kv.js +1 -2
- package/dist/adapters/cloudflare-kv.js.map +1 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/memory.d.ts +9 -0
- package/dist/adapters/memory.d.ts.map +1 -0
- package/dist/adapters/memory.js.map +1 -0
- package/dist/{src/adapters → adapters}/redis.d.ts +3 -3
- package/dist/adapters/redis.d.ts.map +1 -0
- package/dist/adapters/redis.js.map +1 -0
- package/dist/{src/adapters → adapters}/types.d.ts +7 -3
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/{src/adapters → adapters}/types.js.map +1 -1
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +24 -0
- package/dist/discovery.js.map +1 -0
- package/dist/{src/index.d.ts → index.d.ts} +14 -8
- package/dist/index.d.ts.map +1 -0
- package/dist/{src/index.js → index.js} +3 -2
- package/dist/index.js.map +1 -0
- package/dist/middleware.d.ts +28 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +121 -0
- package/dist/middleware.js.map +1 -0
- package/dist/routes.d.ts +5 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/{src/routes.js → routes.js} +14 -4
- package/dist/routes.js.map +1 -0
- package/dist/{src/session.d.ts → session.d.ts} +6 -3
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js.map +1 -0
- package/package.json +8 -4
- package/dist/src/adapters/cloudflare-kv.d.ts +0 -10
- package/dist/src/adapters/cloudflare-kv.d.ts.map +0 -1
- package/dist/src/adapters/cloudflare-kv.js.map +0 -1
- package/dist/src/adapters/index.d.ts.map +0 -1
- package/dist/src/adapters/index.js.map +0 -1
- package/dist/src/adapters/memory.d.ts +0 -9
- package/dist/src/adapters/memory.d.ts.map +0 -1
- package/dist/src/adapters/memory.js.map +0 -1
- package/dist/src/adapters/redis.d.ts.map +0 -1
- package/dist/src/adapters/redis.js.map +0 -1
- package/dist/src/adapters/types.d.ts.map +0 -1
- package/dist/src/discovery.d.ts.map +0 -1
- package/dist/src/discovery.js +0 -19
- package/dist/src/discovery.js.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js.map +0 -1
- package/dist/src/middleware.d.ts +0 -22
- package/dist/src/middleware.d.ts.map +0 -1
- package/dist/src/middleware.js +0 -95
- package/dist/src/middleware.js.map +0 -1
- package/dist/src/routes.d.ts +0 -5
- package/dist/src/routes.d.ts.map +0 -1
- package/dist/src/routes.js.map +0 -1
- package/dist/src/session.d.ts.map +0 -1
- package/dist/src/session.js.map +0 -1
- package/dist/test/index.test.d.ts +0 -2
- package/dist/test/index.test.d.ts.map +0 -1
- package/dist/test/index.test.js +0 -96
- package/dist/test/index.test.js.map +0 -1
- package/dist/test/middleware.test.d.ts +0 -2
- package/dist/test/middleware.test.d.ts.map +0 -1
- package/dist/test/middleware.test.js +0 -340
- package/dist/test/middleware.test.js.map +0 -1
- package/dist/test/routes.test.d.ts +0 -2
- package/dist/test/routes.test.d.ts.map +0 -1
- package/dist/test/routes.test.js +0 -284
- package/dist/test/routes.test.js.map +0 -1
- package/dist/test/session.test.d.ts +0 -2
- package/dist/test/session.test.d.ts.map +0 -1
- package/dist/test/session.test.js +0 -96
- package/dist/test/session.test.js.map +0 -1
- package/dist/vitest.config.d.ts +0 -3
- package/dist/vitest.config.d.ts.map +0 -1
- package/dist/vitest.config.js +0 -10
- package/dist/vitest.config.js.map +0 -1
- /package/dist/{src/adapters → adapters}/index.d.ts +0 -0
- /package/dist/{src/adapters → adapters}/index.js +0 -0
- /package/dist/{src/adapters → adapters}/memory.js +0 -0
- /package/dist/{src/adapters → adapters}/redis.js +0 -0
- /package/dist/{src/adapters → adapters}/types.js +0 -0
- /package/dist/{src/discovery.d.ts → discovery.d.ts} +0 -0
- /package/dist/{src/session.js → session.js} +0 -0
|
@@ -1,340 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { Hono } from 'hono';
|
|
3
|
-
import { createBezzie, MemoryAdapter } from '../src';
|
|
4
|
-
import * as oauth from 'oauth4webapi';
|
|
5
|
-
// Mock oauth4webapi
|
|
6
|
-
vi.mock('oauth4webapi', async () => {
|
|
7
|
-
const actual = await vi.importActual('oauth4webapi');
|
|
8
|
-
return {
|
|
9
|
-
...actual,
|
|
10
|
-
discoveryRequest: vi.fn(),
|
|
11
|
-
processDiscoveryResponse: vi.fn(),
|
|
12
|
-
refreshTokenGrantRequest: vi.fn(),
|
|
13
|
-
processRefreshTokenResponse: vi.fn(),
|
|
14
|
-
validateJwtAccessToken: vi.fn(),
|
|
15
|
-
};
|
|
16
|
-
});
|
|
17
|
-
describe('Middleware', () => {
|
|
18
|
-
let adapter;
|
|
19
|
-
let auth;
|
|
20
|
-
let app;
|
|
21
|
-
const issuer = 'https://test.auth0.com';
|
|
22
|
-
beforeEach(async () => {
|
|
23
|
-
vi.clearAllMocks();
|
|
24
|
-
adapter = new MemoryAdapter();
|
|
25
|
-
const config = {
|
|
26
|
-
issuer,
|
|
27
|
-
clientId: 'test-client-id',
|
|
28
|
-
clientSecret: 'test-client-secret',
|
|
29
|
-
audience: 'https://api.test.com',
|
|
30
|
-
adapter,
|
|
31
|
-
baseUrl: 'https://app.test.com',
|
|
32
|
-
};
|
|
33
|
-
auth = createBezzie(config);
|
|
34
|
-
app = new Hono();
|
|
35
|
-
app.use('/api/*', auth.middleware());
|
|
36
|
-
app.get('/api/me', (c) => {
|
|
37
|
-
return c.json({ user: c.get('user'), accessToken: c.get('accessToken') });
|
|
38
|
-
});
|
|
39
|
-
// Default mock for discovery
|
|
40
|
-
const mockAs = { issuer, jwks_uri: `${issuer}/jwks` };
|
|
41
|
-
vi.mocked(oauth.discoveryRequest).mockResolvedValue({});
|
|
42
|
-
vi.mocked(oauth.processDiscoveryResponse).mockResolvedValue(mockAs);
|
|
43
|
-
});
|
|
44
|
-
it('returns 401 with no cookie', async () => {
|
|
45
|
-
const res = await app.request('/api/me');
|
|
46
|
-
expect(res.status).toBe(401);
|
|
47
|
-
expect(await res.text()).toBe('Unauthorized');
|
|
48
|
-
});
|
|
49
|
-
it('returns 401 with invalid session (not in KV)', async () => {
|
|
50
|
-
const res = await app.request('/api/me', {
|
|
51
|
-
headers: {
|
|
52
|
-
Cookie: '__Host-session=non-existent',
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
expect(res.status).toBe(401);
|
|
56
|
-
});
|
|
57
|
-
it('valid session passes through and sets user on context', async () => {
|
|
58
|
-
const sessionId = 'test-session-id';
|
|
59
|
-
const user = { sub: 'user-123', email: 'user@example.com' };
|
|
60
|
-
await adapter.set(sessionId, {
|
|
61
|
-
accessToken: 'valid-token',
|
|
62
|
-
refreshToken: 'valid-refresh',
|
|
63
|
-
expiresAt: Math.floor(Date.now() / 1000) + 3600,
|
|
64
|
-
createdAt: Math.floor(Date.now() / 1000),
|
|
65
|
-
user,
|
|
66
|
-
}, 3600);
|
|
67
|
-
// Mock successful JWT validation
|
|
68
|
-
vi.mocked(oauth.validateJwtAccessToken).mockResolvedValue({});
|
|
69
|
-
const res = await app.request('/api/me', {
|
|
70
|
-
headers: {
|
|
71
|
-
Cookie: `__Host-session=${sessionId}`,
|
|
72
|
-
},
|
|
73
|
-
});
|
|
74
|
-
expect(res.status).toBe(200);
|
|
75
|
-
const data = (await res.json());
|
|
76
|
-
expect(data.user).toEqual(user);
|
|
77
|
-
expect(data.accessToken).toBe('valid-token');
|
|
78
|
-
});
|
|
79
|
-
it('expired access token triggers refresh, updates KV, passes through', async () => {
|
|
80
|
-
const sessionId = 'test-session-id';
|
|
81
|
-
const user = { sub: 'user-123' };
|
|
82
|
-
await adapter.set(sessionId, {
|
|
83
|
-
accessToken: 'expired-token',
|
|
84
|
-
refreshToken: 'valid-refresh',
|
|
85
|
-
expiresAt: Math.floor(Date.now() / 1000) - 10, // expired 10s ago
|
|
86
|
-
createdAt: Math.floor(Date.now() / 1000) - 1000,
|
|
87
|
-
user,
|
|
88
|
-
}, 86400);
|
|
89
|
-
// Mock successful refresh
|
|
90
|
-
vi.mocked(oauth.refreshTokenGrantRequest).mockResolvedValue({});
|
|
91
|
-
vi.mocked(oauth.processRefreshTokenResponse).mockResolvedValue({
|
|
92
|
-
access_token: 'new-token',
|
|
93
|
-
refresh_token: 'new-refresh',
|
|
94
|
-
expires_in: 3600,
|
|
95
|
-
token_type: 'bearer',
|
|
96
|
-
});
|
|
97
|
-
vi.mocked(oauth.validateJwtAccessToken).mockResolvedValue({});
|
|
98
|
-
const res = await app.request('/api/me', {
|
|
99
|
-
headers: {
|
|
100
|
-
Cookie: `__Host-session=${sessionId}`,
|
|
101
|
-
},
|
|
102
|
-
});
|
|
103
|
-
expect(res.status).toBe(200);
|
|
104
|
-
const data = (await res.json());
|
|
105
|
-
expect(data.accessToken).toBe('new-token');
|
|
106
|
-
// Check adapter updated
|
|
107
|
-
const stored = (await adapter.get(sessionId));
|
|
108
|
-
expect(stored.accessToken).toBe('new-token');
|
|
109
|
-
expect(stored.refreshToken).toBe('new-refresh');
|
|
110
|
-
expect(stored.expiresAt).toBeGreaterThan(Date.now() / 1000);
|
|
111
|
-
});
|
|
112
|
-
it('failed refresh deletes session and returns 401', async () => {
|
|
113
|
-
const sessionId = 'test-session-id';
|
|
114
|
-
await adapter.set(sessionId, {
|
|
115
|
-
accessToken: 'expired-token',
|
|
116
|
-
refreshToken: 'invalid-refresh',
|
|
117
|
-
expiresAt: Math.floor(Date.now() / 1000) - 10,
|
|
118
|
-
createdAt: Math.floor(Date.now() / 1000) - 1000,
|
|
119
|
-
user: { sub: '123' },
|
|
120
|
-
}, 3600);
|
|
121
|
-
// Mock failed refresh
|
|
122
|
-
vi.mocked(oauth.refreshTokenGrantRequest).mockResolvedValue({});
|
|
123
|
-
const error = new oauth.ResponseBodyError('invalid_grant', {
|
|
124
|
-
cause: { error: 'invalid_grant' },
|
|
125
|
-
response: new Response()
|
|
126
|
-
});
|
|
127
|
-
vi.mocked(oauth.processRefreshTokenResponse).mockRejectedValue(error);
|
|
128
|
-
const res = await app.request('/api/me', {
|
|
129
|
-
headers: {
|
|
130
|
-
Cookie: `__Host-session=${sessionId}`,
|
|
131
|
-
},
|
|
132
|
-
});
|
|
133
|
-
expect(res.status).toBe(401);
|
|
134
|
-
// Check session deleted
|
|
135
|
-
expect(await adapter.get(sessionId)).toBeNull();
|
|
136
|
-
});
|
|
137
|
-
it('invalid JWT returns 401', async () => {
|
|
138
|
-
const sessionId = 'test-session-id';
|
|
139
|
-
await adapter.set(sessionId, {
|
|
140
|
-
accessToken: 'invalid-jwt',
|
|
141
|
-
refreshToken: 'refresh',
|
|
142
|
-
expiresAt: Math.floor(Date.now() / 1000) + 3600,
|
|
143
|
-
createdAt: Math.floor(Date.now() / 1000),
|
|
144
|
-
user: { sub: '123' },
|
|
145
|
-
}, 3600);
|
|
146
|
-
// Mock JWT validation failure
|
|
147
|
-
vi.mocked(oauth.validateJwtAccessToken).mockRejectedValue(new Error('Invalid token'));
|
|
148
|
-
const res = await app.request('/api/me', {
|
|
149
|
-
headers: {
|
|
150
|
-
Cookie: `__Host-session=${sessionId}`,
|
|
151
|
-
},
|
|
152
|
-
});
|
|
153
|
-
expect(res.status).toBe(401);
|
|
154
|
-
});
|
|
155
|
-
it('triggers refresh with 60s buffer', async () => {
|
|
156
|
-
const sessionId = 'test-session-id';
|
|
157
|
-
await adapter.set(sessionId, {
|
|
158
|
-
accessToken: 'near-expiry-token',
|
|
159
|
-
refreshToken: 'valid-refresh',
|
|
160
|
-
expiresAt: Math.floor(Date.now() / 1000) + 30, // expires in 30s
|
|
161
|
-
createdAt: Math.floor(Date.now() / 1000) - 1000,
|
|
162
|
-
user: { sub: '123' },
|
|
163
|
-
}, 3600);
|
|
164
|
-
vi.mocked(oauth.refreshTokenGrantRequest).mockResolvedValue({});
|
|
165
|
-
vi.mocked(oauth.processRefreshTokenResponse).mockResolvedValue({
|
|
166
|
-
access_token: 'new-token',
|
|
167
|
-
expires_in: 3600,
|
|
168
|
-
token_type: 'bearer',
|
|
169
|
-
});
|
|
170
|
-
vi.mocked(oauth.validateJwtAccessToken).mockResolvedValue({});
|
|
171
|
-
const res = await app.request('/api/me', {
|
|
172
|
-
headers: {
|
|
173
|
-
Cookie: `__Host-session=${sessionId}`,
|
|
174
|
-
},
|
|
175
|
-
});
|
|
176
|
-
expect(res.status).toBe(200);
|
|
177
|
-
const data = (await res.json());
|
|
178
|
-
expect(data.accessToken).toBe('new-token');
|
|
179
|
-
});
|
|
180
|
-
it('skips JWT validation when no audience is configured', async () => {
|
|
181
|
-
// Create a new app/middleware with no audience
|
|
182
|
-
const configNoAudience = {
|
|
183
|
-
issuer,
|
|
184
|
-
clientId: 'test-client-id',
|
|
185
|
-
clientSecret: 'test-client-secret',
|
|
186
|
-
// no audience
|
|
187
|
-
adapter,
|
|
188
|
-
baseUrl: 'https://app.test.com',
|
|
189
|
-
};
|
|
190
|
-
const authNoAudience = createBezzie(configNoAudience);
|
|
191
|
-
const appNoAudience = new Hono();
|
|
192
|
-
appNoAudience.use('/api/*', authNoAudience.middleware());
|
|
193
|
-
appNoAudience.get('/api/me', (c) => c.json({ ok: true }));
|
|
194
|
-
const sessionId = 'test-session-id';
|
|
195
|
-
await adapter.set(sessionId, {
|
|
196
|
-
accessToken: 'valid-token',
|
|
197
|
-
refreshToken: 'valid-refresh',
|
|
198
|
-
expiresAt: Math.floor(Date.now() / 1000) + 3600,
|
|
199
|
-
createdAt: Math.floor(Date.now() / 1000),
|
|
200
|
-
user: { sub: '123' },
|
|
201
|
-
}, 3600);
|
|
202
|
-
const res = await appNoAudience.request('/api/me', {
|
|
203
|
-
headers: {
|
|
204
|
-
Cookie: `__Host-session=${sessionId}`,
|
|
205
|
-
},
|
|
206
|
-
});
|
|
207
|
-
expect(res.status).toBe(200);
|
|
208
|
-
// Should NOT have called validateJwtAccessToken
|
|
209
|
-
expect(oauth.validateJwtAccessToken).not.toHaveBeenCalled();
|
|
210
|
-
});
|
|
211
|
-
it('skips JWT validation when validateAccessToken is false', async () => {
|
|
212
|
-
const configWithValidateFalse = {
|
|
213
|
-
issuer,
|
|
214
|
-
clientId: 'test-client-id',
|
|
215
|
-
clientSecret: 'test-client-secret',
|
|
216
|
-
audience: 'https://api.test.com',
|
|
217
|
-
adapter,
|
|
218
|
-
baseUrl: 'https://app.test.com',
|
|
219
|
-
validateAccessToken: false,
|
|
220
|
-
};
|
|
221
|
-
const authWithValidateFalse = createBezzie(configWithValidateFalse);
|
|
222
|
-
const appWithValidateFalse = new Hono();
|
|
223
|
-
appWithValidateFalse.use('/api/*', authWithValidateFalse.middleware());
|
|
224
|
-
appWithValidateFalse.get('/api/me', (c) => c.json({ ok: true }));
|
|
225
|
-
const sessionId = 'test-session-id';
|
|
226
|
-
await adapter.set(sessionId, {
|
|
227
|
-
accessToken: 'opaque-token',
|
|
228
|
-
refreshToken: 'valid-refresh',
|
|
229
|
-
expiresAt: Math.floor(Date.now() / 1000) + 3600,
|
|
230
|
-
createdAt: Math.floor(Date.now() / 1000),
|
|
231
|
-
user: { sub: '123' },
|
|
232
|
-
}, 3600);
|
|
233
|
-
const res = await appWithValidateFalse.request('/api/me', {
|
|
234
|
-
headers: {
|
|
235
|
-
Cookie: `__Host-session=${sessionId}`,
|
|
236
|
-
},
|
|
237
|
-
});
|
|
238
|
-
expect(res.status).toBe(200);
|
|
239
|
-
expect(oauth.validateJwtAccessToken).not.toHaveBeenCalled();
|
|
240
|
-
});
|
|
241
|
-
it('re-reads session from store when refresh fails with invalid_grant (race condition)', async () => {
|
|
242
|
-
const sessionId = 'test-session-id';
|
|
243
|
-
const user = { sub: 'user-123' };
|
|
244
|
-
const oldAccessToken = 'expired-token';
|
|
245
|
-
const newAccessToken = 'already-refreshed-token';
|
|
246
|
-
// Initial state: near-expiry token
|
|
247
|
-
await adapter.set(sessionId, {
|
|
248
|
-
accessToken: oldAccessToken,
|
|
249
|
-
refreshToken: 'valid-refresh',
|
|
250
|
-
expiresAt: Math.floor(Date.now() / 1000) + 30, // expires in 30s
|
|
251
|
-
createdAt: Math.floor(Date.now() / 1000),
|
|
252
|
-
user,
|
|
253
|
-
}, 86400);
|
|
254
|
-
// Mock failed refresh with invalid_grant
|
|
255
|
-
vi.mocked(oauth.refreshTokenGrantRequest).mockResolvedValue({});
|
|
256
|
-
const error = new oauth.ResponseBodyError('invalid_grant', {
|
|
257
|
-
cause: { error: 'invalid_grant' },
|
|
258
|
-
response: new Response()
|
|
259
|
-
});
|
|
260
|
-
vi.mocked(oauth.processRefreshTokenResponse).mockRejectedValue(error);
|
|
261
|
-
vi.mocked(oauth.validateJwtAccessToken).mockResolvedValue({});
|
|
262
|
-
const originalGet = adapter.get.bind(adapter);
|
|
263
|
-
let getCount = 0;
|
|
264
|
-
vi.spyOn(adapter, 'get').mockImplementation(async (id) => {
|
|
265
|
-
getCount++;
|
|
266
|
-
const result = await originalGet(id);
|
|
267
|
-
if (getCount === 1) {
|
|
268
|
-
// After first GET, update adapter to simulate concurrent refresh by another request
|
|
269
|
-
await adapter.set(id, {
|
|
270
|
-
accessToken: newAccessToken,
|
|
271
|
-
refreshToken: 'new-refresh',
|
|
272
|
-
expiresAt: Math.floor(Date.now() / 1000) + 3600,
|
|
273
|
-
createdAt: Math.floor(Date.now() / 1000),
|
|
274
|
-
user,
|
|
275
|
-
}, 86400);
|
|
276
|
-
}
|
|
277
|
-
return result;
|
|
278
|
-
});
|
|
279
|
-
const res = await app.request('/api/me', {
|
|
280
|
-
headers: {
|
|
281
|
-
Cookie: `__Host-session=${sessionId}`,
|
|
282
|
-
},
|
|
283
|
-
});
|
|
284
|
-
expect(res.status).toBe(200);
|
|
285
|
-
const data = (await res.json());
|
|
286
|
-
expect(data.accessToken).toBe(newAccessToken);
|
|
287
|
-
// Verify it was re-read (1st in middleware start, 2nd after invalid_grant)
|
|
288
|
-
expect(getCount).toBe(2);
|
|
289
|
-
});
|
|
290
|
-
it('redirects to login when session is older than 90 days (absolute expiry)', async () => {
|
|
291
|
-
const sessionId = 'old-session-id';
|
|
292
|
-
const MAX_SESSION_AGE = 90 * 24 * 60 * 60;
|
|
293
|
-
await adapter.set(sessionId, {
|
|
294
|
-
accessToken: 'token',
|
|
295
|
-
refreshToken: 'refresh',
|
|
296
|
-
expiresAt: Math.floor(Date.now() / 1000) + 3600,
|
|
297
|
-
createdAt: Math.floor(Date.now() / 1000) - (MAX_SESSION_AGE + 1), // 90 days + 1 second ago
|
|
298
|
-
user: { sub: 'user-123' },
|
|
299
|
-
}, 3600);
|
|
300
|
-
const res = await app.request('/api/me', {
|
|
301
|
-
headers: {
|
|
302
|
-
Cookie: `__Host-session=${sessionId}`,
|
|
303
|
-
},
|
|
304
|
-
});
|
|
305
|
-
expect(res.status).toBe(302);
|
|
306
|
-
expect(res.headers.get('Location')).toBe('/auth/login');
|
|
307
|
-
// Session should be deleted from store
|
|
308
|
-
expect(await adapter.get(sessionId)).toBeNull();
|
|
309
|
-
});
|
|
310
|
-
it('redirects to custom login path when session is older than 90 days', async () => {
|
|
311
|
-
const configWithCustomLogin = {
|
|
312
|
-
issuer,
|
|
313
|
-
clientId: 'test-client-id',
|
|
314
|
-
clientSecret: 'test-client-secret',
|
|
315
|
-
adapter,
|
|
316
|
-
baseUrl: 'https://app.test.com',
|
|
317
|
-
loginPath: '/custom/login',
|
|
318
|
-
};
|
|
319
|
-
const authCustomLogin = createBezzie(configWithCustomLogin);
|
|
320
|
-
const appCustomLogin = new Hono();
|
|
321
|
-
appCustomLogin.use('/api/*', authCustomLogin.middleware());
|
|
322
|
-
const sessionId = 'old-session-id';
|
|
323
|
-
const MAX_SESSION_AGE = 90 * 24 * 60 * 60;
|
|
324
|
-
await adapter.set(sessionId, {
|
|
325
|
-
accessToken: 'token',
|
|
326
|
-
refreshToken: 'refresh',
|
|
327
|
-
expiresAt: Math.floor(Date.now() / 1000) + 3600,
|
|
328
|
-
createdAt: Math.floor(Date.now() / 1000) - (MAX_SESSION_AGE + 1),
|
|
329
|
-
user: { sub: 'user-123' },
|
|
330
|
-
}, 3600);
|
|
331
|
-
const res = await appCustomLogin.request('/api/me', {
|
|
332
|
-
headers: {
|
|
333
|
-
Cookie: `__Host-session=${sessionId}`,
|
|
334
|
-
},
|
|
335
|
-
});
|
|
336
|
-
expect(res.status).toBe(302);
|
|
337
|
-
expect(res.headers.get('Location')).toBe('/custom/login');
|
|
338
|
-
});
|
|
339
|
-
});
|
|
340
|
-
//# sourceMappingURL=middleware.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.test.js","sourceRoot":"","sources":["../../test/middleware.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,YAAY,EAAE,aAAa,EAA6C,MAAM,QAAQ,CAAA;AAC/F,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,oBAAoB;AACpB,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,IAAI,EAAE;IACjC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,YAAY,CAAC,cAAc,CAAC,CAAA;IACpD,OAAO;QACL,GAAG,MAAM;QACT,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;QACzB,wBAAwB,EAAE,EAAE,CAAC,EAAE,EAAE;QACjC,wBAAwB,EAAE,EAAE,CAAC,EAAE,EAAE;QACjC,2BAA2B,EAAE,EAAE,CAAC,EAAE,EAAE;QACpC,sBAAsB,EAAE,EAAE,CAAC,EAAE,EAAE;KAChC,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,IAAI,OAAsB,CAAA;IAC1B,IAAI,IAAY,CAAA;IAChB,IAAI,GAAmC,CAAA;IACvC,MAAM,MAAM,GAAG,wBAAwB,CAAA;IAEvC,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,EAAE,CAAC,aAAa,EAAE,CAAA;QAClB,OAAO,GAAG,IAAI,aAAa,EAAE,CAAA;QAC7B,MAAM,MAAM,GAAG;YACb,MAAM;YACN,QAAQ,EAAE,gBAAgB;YAC1B,YAAY,EAAE,oBAAoB;YAClC,QAAQ,EAAE,sBAAsB;YAChC,OAAO;YACP,OAAO,EAAE,sBAAsB;SAChC,CAAA;QAED,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;QAC3B,GAAG,GAAG,IAAI,IAAI,EAA4B,CAAA;QAE1C,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAA;QACpC,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;YACvB,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;QAC3E,CAAC,CAAC,CAAA;QAEF,6BAA6B;QAC7B,MAAM,MAAM,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,OAAO,EAAE,CAAA;QACrD,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,CAAC,EAAyB,CAAC,CAAA;QAC9E,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,iBAAiB,CAAC,MAAmC,CAAC,CAAA;IAClG,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QACxC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE;YACvC,OAAO,EAAE;gBACP,MAAM,EAAE,6BAA6B;aACtC;SACF,CAAC,CAAA;QACF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC9B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,SAAS,GAAG,iBAAiB,CAAA;QACnC,MAAM,IAAI,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAA;QAC3D,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,EACT;YACE,WAAW,EAAE,aAAa;YAC1B,YAAY,EAAE,eAAe;YAC7B,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;YAC/C,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YACxC,IAAI;SACL,EACD,IAAI,CACL,CAAA;QAED,iCAAiC;QACjC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,iBAAiB,CAAC,EAAgC,CAAC,CAAA;QAE3F,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE;YACvC,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB,SAAS,EAAE;aACtC;SACF,CAAC,CAAA;QAEF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA6D,CAAA;QAC3F,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC/B,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IAC9C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,SAAS,GAAG,iBAAiB,CAAA;QACnC,MAAM,IAAI,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,CAAA;QAChC,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,EACT;YACE,WAAW,EAAE,eAAe;YAC5B,YAAY,EAAE,eAAe;YAC7B,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,kBAAkB;YACjE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;YAC/C,IAAI;SACL,EACD,KAAK,CACN,CAAA;QAED,0BAA0B;QAC1B,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,iBAAiB,CAAC,EAAc,CAAC,CAAA;QAC3E,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,iBAAiB,CAAC;YAC7D,YAAY,EAAE,WAAW;YACzB,aAAa,EAAE,aAAa;YAC5B,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,QAAQ;SACU,CAAC,CAAA;QACjC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,iBAAiB,CAAC,EAAgC,CAAC,CAAA;QAE3F,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE;YACvC,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB,SAAS,EAAE;aACtC;SACF,CAAC,CAAA;QAEF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA6D,CAAA;QAC3F,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAE1C,wBAAwB;QACxB,MAAM,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAY,CAAA;QACxD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAC5C,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAC/C,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;IAC7D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,SAAS,GAAG,iBAAiB,CAAA;QACnC,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,EACT;YACE,WAAW,EAAE,eAAe;YAC5B,YAAY,EAAE,iBAAiB;YAC/B,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE;YAC7C,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;YAC/C,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;SACrB,EACD,IAAI,CACL,CAAA;QAED,sBAAsB;QACtB,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,iBAAiB,CAAC,EAAc,CAAC,CAAA;QAC3E,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,iBAAiB,CAAC,eAAe,EAAE;YACzD,KAAK,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE;YACjC,QAAQ,EAAE,IAAI,QAAQ,EAAE;SACzB,CAAC,CAAA;QACF,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAA;QAErE,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE;YACvC,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB,SAAS,EAAE;aACtC;SACF,CAAC,CAAA;QAEF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAE5B,wBAAwB;QACxB,MAAM,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;IACjD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yBAAyB,EAAE,KAAK,IAAI,EAAE;QACvC,MAAM,SAAS,GAAG,iBAAiB,CAAA;QACnC,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,EACT;YACE,WAAW,EAAE,aAAa;YAC1B,YAAY,EAAE,SAAS;YACvB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;YAC/C,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YACxC,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;SACrB,EACD,IAAI,CACL,CAAA;QAED,8BAA8B;QAC9B,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAA;QAErF,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE;YACvC,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB,SAAS,EAAE;aACtC;SACF,CAAC,CAAA;QAEF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC9B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,SAAS,GAAG,iBAAiB,CAAA;QACnC,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,EACT;YACE,WAAW,EAAE,mBAAmB;YAChC,YAAY,EAAE,eAAe;YAC7B,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,iBAAiB;YAChE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;YAC/C,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;SACrB,EACD,IAAI,CACL,CAAA;QAED,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,iBAAiB,CAAC,EAAc,CAAC,CAAA;QAC3E,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,iBAAiB,CAAC;YAC7D,YAAY,EAAE,WAAW;YACzB,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,QAAQ;SACU,CAAC,CAAA;QACjC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,iBAAiB,CAAC,EAAgC,CAAC,CAAA;QAE3F,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE;YACvC,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB,SAAS,EAAE;aACtC;SACF,CAAC,CAAA;QAEF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA6D,CAAA;QAC3F,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IAC5C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,+CAA+C;QAC/C,MAAM,gBAAgB,GAAG;YACvB,MAAM;YACN,QAAQ,EAAE,gBAAgB;YAC1B,YAAY,EAAE,oBAAoB;YAClC,cAAc;YACd,OAAO;YACP,OAAO,EAAE,sBAAsB;SAChC,CAAA;QACD,MAAM,cAAc,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAA;QACrD,MAAM,aAAa,GAAG,IAAI,IAAI,EAAE,CAAA;QAChC,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,EAAE,CAAC,CAAA;QACxD,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QAEzD,MAAM,SAAS,GAAG,iBAAiB,CAAA;QACnC,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE;YAC3B,WAAW,EAAE,aAAa;YAC1B,YAAY,EAAE,eAAe;YAC7B,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;YAC/C,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YACxC,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;SACrB,EAAE,IAAI,CAAC,CAAA;QAER,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,SAAS,EAAE;YACjD,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB,SAAS,EAAE;aACtC;SACF,CAAC,CAAA;QAEF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,gDAAgD;QAChD,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAA;IAC7D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,MAAM,uBAAuB,GAAG;YAC9B,MAAM;YACN,QAAQ,EAAE,gBAAgB;YAC1B,YAAY,EAAE,oBAAoB;YAClC,QAAQ,EAAE,sBAAsB;YAChC,OAAO;YACP,OAAO,EAAE,sBAAsB;YAC/B,mBAAmB,EAAE,KAAK;SAC3B,CAAA;QACD,MAAM,qBAAqB,GAAG,YAAY,CAAC,uBAAuB,CAAC,CAAA;QACnE,MAAM,oBAAoB,GAAG,IAAI,IAAI,EAAE,CAAA;QACvC,oBAAoB,CAAC,GAAG,CAAC,QAAQ,EAAE,qBAAqB,CAAC,UAAU,EAAE,CAAC,CAAA;QACtE,oBAAoB,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QAEhE,MAAM,SAAS,GAAG,iBAAiB,CAAA;QACnC,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE;YAC3B,WAAW,EAAE,cAAc;YAC3B,YAAY,EAAE,eAAe;YAC7B,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;YAC/C,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YACxC,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;SACrB,EAAE,IAAI,CAAC,CAAA;QAER,MAAM,GAAG,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,SAAS,EAAE;YACxD,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB,SAAS,EAAE;aACtC;SACF,CAAC,CAAA;QAEF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAA;IAC7D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;QAClG,MAAM,SAAS,GAAG,iBAAiB,CAAA;QACnC,MAAM,IAAI,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,CAAA;QAChC,MAAM,cAAc,GAAG,eAAe,CAAA;QACtC,MAAM,cAAc,GAAG,yBAAyB,CAAA;QAEhD,mCAAmC;QACnC,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,EACT;YACE,WAAW,EAAE,cAAc;YAC3B,YAAY,EAAE,eAAe;YAC7B,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,iBAAiB;YAChE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YACxC,IAAI;SACL,EACD,KAAK,CACN,CAAA;QAED,yCAAyC;QACzC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,iBAAiB,CAAC,EAAc,CAAC,CAAA;QAC3E,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,iBAAiB,CAAC,eAAe,EAAE;YACzD,KAAK,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE;YACjC,QAAQ,EAAE,IAAI,QAAQ,EAAE;SACzB,CAAC,CAAA;QACF,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAA;QACrE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,iBAAiB,CAAC,EAAgC,CAAC,CAAA;QAE3F,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC7C,IAAI,QAAQ,GAAG,CAAC,CAAA;QAChB,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAE,EAAU,EAAE,EAAE;YAC/D,QAAQ,EAAE,CAAA;YACV,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,EAAE,CAAC,CAAA;YACpC,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;gBACnB,oFAAoF;gBACpF,MAAM,OAAO,CAAC,GAAG,CACf,EAAE,EACF;oBACE,WAAW,EAAE,cAAc;oBAC3B,YAAY,EAAE,aAAa;oBAC3B,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;oBAC/C,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;oBACxC,IAAI;iBACL,EACD,KAAK,CACN,CAAA;YACH,CAAC;YACD,OAAO,MAAM,CAAA;QACf,CAAC,CAAC,CAAA;QAEF,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE;YACvC,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB,SAAS,EAAE;aACtC;SACF,CAAC,CAAA;QAEF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA6D,CAAA;QAC3F,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;QAE7C,2EAA2E;QAC3E,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC1B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,SAAS,GAAG,gBAAgB,CAAA;QAClC,MAAM,eAAe,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;QACzC,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,EACT;YACE,WAAW,EAAE,OAAO;YACpB,YAAY,EAAE,SAAS;YACvB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;YAC/C,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,CAAC,CAAC,EAAE,yBAAyB;YAC3F,IAAI,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE;SAC1B,EACD,IAAI,CACL,CAAA;QAED,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE;YACvC,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB,SAAS,EAAE;aACtC;SACF,CAAC,CAAA;QAEF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAEvD,uCAAuC;QACvC,MAAM,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;IACjD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,qBAAqB,GAAG;YAC5B,MAAM;YACN,QAAQ,EAAE,gBAAgB;YAC1B,YAAY,EAAE,oBAAoB;YAClC,OAAO;YACP,OAAO,EAAE,sBAAsB;YAC/B,SAAS,EAAE,eAAe;SAC3B,CAAA;QACD,MAAM,eAAe,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAA;QAC3D,MAAM,cAAc,GAAG,IAAI,IAAI,EAAE,CAAA;QACjC,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,UAAU,EAAE,CAAC,CAAA;QAE1D,MAAM,SAAS,GAAG,gBAAgB,CAAA;QAClC,MAAM,eAAe,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;QACzC,MAAM,OAAO,CAAC,GAAG,CACf,SAAS,EACT;YACE,WAAW,EAAE,OAAO;YACpB,YAAY,EAAE,SAAS;YACvB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI;YAC/C,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,CAAC,CAAC;YAChE,IAAI,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE;SAC1B,EACD,IAAI,CACL,CAAA;QAED,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,SAAS,EAAE;YAClD,OAAO,EAAE;gBACP,MAAM,EAAE,kBAAkB,SAAS,EAAE;aACtC;SACF,CAAC,CAAA;QAEF,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"routes.test.d.ts","sourceRoot":"","sources":["../../test/routes.test.ts"],"names":[],"mappings":""}
|
package/dist/test/routes.test.js
DELETED
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import { createBezzie, MemoryAdapter } from '../src';
|
|
3
|
-
import * as oauth from 'oauth4webapi';
|
|
4
|
-
// Mock oauth4webapi
|
|
5
|
-
vi.mock('oauth4webapi', async () => {
|
|
6
|
-
const actual = await vi.importActual('oauth4webapi');
|
|
7
|
-
return {
|
|
8
|
-
...actual,
|
|
9
|
-
discoveryRequest: vi.fn(),
|
|
10
|
-
processDiscoveryResponse: vi.fn(),
|
|
11
|
-
authorizationCodeGrantRequest: vi.fn(),
|
|
12
|
-
processAuthorizationCodeResponse: vi.fn(),
|
|
13
|
-
getValidatedIdTokenClaims: vi.fn(),
|
|
14
|
-
};
|
|
15
|
-
});
|
|
16
|
-
describe('OAuth Routes', () => {
|
|
17
|
-
const adapter = new MemoryAdapter();
|
|
18
|
-
const config = {
|
|
19
|
-
issuer: 'https://test.auth0.com',
|
|
20
|
-
clientId: 'test-client-id',
|
|
21
|
-
clientSecret: 'test-client-secret',
|
|
22
|
-
audience: 'https://api.test.com',
|
|
23
|
-
adapter,
|
|
24
|
-
baseUrl: 'https://app.test.com',
|
|
25
|
-
};
|
|
26
|
-
const auth = createBezzie(config);
|
|
27
|
-
const app = auth.routes();
|
|
28
|
-
describe('GET /login', () => {
|
|
29
|
-
it('redirects to the provider authorization URL', async () => {
|
|
30
|
-
auth.cache.cachedAS = null;
|
|
31
|
-
auth.cache.cacheExpiresAt = 0;
|
|
32
|
-
const mockAs = {
|
|
33
|
-
issuer: config.issuer,
|
|
34
|
-
authorization_endpoint: `${config.issuer}/authorize`
|
|
35
|
-
};
|
|
36
|
-
vi.mocked(oauth.discoveryRequest).mockResolvedValue({});
|
|
37
|
-
vi.mocked(oauth.processDiscoveryResponse).mockResolvedValue(mockAs);
|
|
38
|
-
const res = await app.request('/login');
|
|
39
|
-
expect(res.status).toBe(302);
|
|
40
|
-
const location = res.headers.get('Location');
|
|
41
|
-
expect(location).toContain(`${config.issuer}/authorize`);
|
|
42
|
-
expect(location).toContain(`client_id=${config.clientId}`);
|
|
43
|
-
expect(location).toContain('response_type=code');
|
|
44
|
-
expect(location).toContain(`redirect_uri=${encodeURIComponent(config.baseUrl + '/auth/callback')}`);
|
|
45
|
-
expect(location).toContain('scope=openid+profile+email+offline_access');
|
|
46
|
-
expect(location).toContain('code_challenge=');
|
|
47
|
-
expect(location).toContain('code_challenge_method=S256');
|
|
48
|
-
expect(location).toContain(`audience=${encodeURIComponent(config.audience)}`);
|
|
49
|
-
});
|
|
50
|
-
it('stores PKCE state in adapter', async () => {
|
|
51
|
-
auth.cache.cachedAS = null;
|
|
52
|
-
auth.cache.cacheExpiresAt = 0;
|
|
53
|
-
const mockAs = {
|
|
54
|
-
issuer: config.issuer,
|
|
55
|
-
authorization_endpoint: `${config.issuer}/authorize`
|
|
56
|
-
};
|
|
57
|
-
vi.mocked(oauth.discoveryRequest).mockResolvedValue({});
|
|
58
|
-
vi.mocked(oauth.processDiscoveryResponse).mockResolvedValue(mockAs);
|
|
59
|
-
const res = await app.request('/login');
|
|
60
|
-
const location = new URL(res.headers.get('Location'));
|
|
61
|
-
const state = location.searchParams.get('state');
|
|
62
|
-
const stored = await adapter.get(`pkce:${state}`);
|
|
63
|
-
expect(stored).toBeDefined();
|
|
64
|
-
expect(typeof stored.codeVerifier).toBe('string');
|
|
65
|
-
});
|
|
66
|
-
it('stores returnTo in PKCE state if provided', async () => {
|
|
67
|
-
auth.cache.cachedAS = null;
|
|
68
|
-
auth.cache.cacheExpiresAt = 0;
|
|
69
|
-
const mockAs = {
|
|
70
|
-
issuer: config.issuer,
|
|
71
|
-
authorization_endpoint: `${config.issuer}/authorize`
|
|
72
|
-
};
|
|
73
|
-
vi.mocked(oauth.discoveryRequest).mockResolvedValue({});
|
|
74
|
-
vi.mocked(oauth.processDiscoveryResponse).mockResolvedValue(mockAs);
|
|
75
|
-
const res = await app.request('/login?returnTo=/dashboard');
|
|
76
|
-
const location = new URL(res.headers.get('Location'));
|
|
77
|
-
const state = location.searchParams.get('state');
|
|
78
|
-
const stored = await adapter.get(`pkce:${state}`);
|
|
79
|
-
expect(stored.returnTo).toBe('/dashboard');
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
describe('GET /callback', () => {
|
|
83
|
-
it('returns 400 with error parameter', async () => {
|
|
84
|
-
const res = await app.request('/callback?error=access_denied');
|
|
85
|
-
expect(res.status).toBe(400);
|
|
86
|
-
expect(await res.text()).toBe('OAuth error: access_denied');
|
|
87
|
-
});
|
|
88
|
-
it('returns 400 with invalid state', async () => {
|
|
89
|
-
const res = await app.request('/callback?state=invalid&code=123');
|
|
90
|
-
expect(res.status).toBe(400);
|
|
91
|
-
expect(await res.text()).toBe('Invalid or expired state');
|
|
92
|
-
});
|
|
93
|
-
it('with valid state exchanges code, stores session, sets cookie, redirects', async () => {
|
|
94
|
-
const state = 'test-state';
|
|
95
|
-
const code = 'test-code';
|
|
96
|
-
const codeVerifier = 'test-verifier';
|
|
97
|
-
await adapter.set(`pkce:${state}`, { codeVerifier }, 600);
|
|
98
|
-
// Setup mocks
|
|
99
|
-
const mockAs = { issuer: config.issuer };
|
|
100
|
-
vi.mocked(oauth.discoveryRequest).mockResolvedValue({});
|
|
101
|
-
vi.mocked(oauth.processDiscoveryResponse).mockResolvedValue(mockAs);
|
|
102
|
-
vi.mocked(oauth.authorizationCodeGrantRequest).mockResolvedValue({});
|
|
103
|
-
vi.mocked(oauth.processAuthorizationCodeResponse).mockResolvedValue({
|
|
104
|
-
access_token: 'mock-access-token',
|
|
105
|
-
refresh_token: 'mock-refresh-token',
|
|
106
|
-
expires_in: 3600,
|
|
107
|
-
id_token: 'mock-id-token',
|
|
108
|
-
});
|
|
109
|
-
vi.mocked(oauth.getValidatedIdTokenClaims).mockReturnValue({
|
|
110
|
-
sub: 'user-123',
|
|
111
|
-
email: 'user@example.com',
|
|
112
|
-
});
|
|
113
|
-
const res = await app.request(`/callback?state=${state}&code=${code}`);
|
|
114
|
-
expect(res.status).toBe(302);
|
|
115
|
-
expect(res.headers.get('Location')).toBe('/');
|
|
116
|
-
// Check cookie
|
|
117
|
-
const cookie = res.headers.get('Set-Cookie');
|
|
118
|
-
expect(cookie).toContain('__Host-session=');
|
|
119
|
-
expect(cookie).toContain('HttpOnly');
|
|
120
|
-
expect(cookie).toContain('Secure');
|
|
121
|
-
expect(cookie).toContain('SameSite=Strict');
|
|
122
|
-
expect(cookie).toContain('Max-Age=2592000');
|
|
123
|
-
// Check session in adapter
|
|
124
|
-
const sessionId = cookie.match(/__Host-session=([^;]+)/)[1];
|
|
125
|
-
const session = await adapter.get(sessionId);
|
|
126
|
-
expect(session).toBeDefined();
|
|
127
|
-
expect(session.accessToken).toBe('mock-access-token');
|
|
128
|
-
expect(session.idToken).toBe('mock-id-token');
|
|
129
|
-
expect(session.user.sub).toBe('user-123');
|
|
130
|
-
expect(session.createdAt).toBeTypeOf('number');
|
|
131
|
-
expect(session.createdAt).toBeLessThanOrEqual(Math.floor(Date.now() / 1000));
|
|
132
|
-
expect(await adapter.get(`pkce:${state}`)).toBeNull();
|
|
133
|
-
});
|
|
134
|
-
it('redirects to returnTo after successful login', async () => {
|
|
135
|
-
const state = 'test-state-ret';
|
|
136
|
-
const code = 'test-code';
|
|
137
|
-
const codeVerifier = 'test-verifier';
|
|
138
|
-
const returnTo = '/dashboard';
|
|
139
|
-
await adapter.set(`pkce:${state}`, { codeVerifier, returnTo }, 600);
|
|
140
|
-
// Setup mocks
|
|
141
|
-
const mockAs = { issuer: config.issuer };
|
|
142
|
-
vi.mocked(oauth.discoveryRequest).mockResolvedValue({});
|
|
143
|
-
vi.mocked(oauth.processDiscoveryResponse).mockResolvedValue(mockAs);
|
|
144
|
-
vi.mocked(oauth.authorizationCodeGrantRequest).mockResolvedValue({});
|
|
145
|
-
vi.mocked(oauth.processAuthorizationCodeResponse).mockResolvedValue({
|
|
146
|
-
access_token: 'mock-access-token',
|
|
147
|
-
expires_in: 3600,
|
|
148
|
-
id_token: 'mock-id-token',
|
|
149
|
-
});
|
|
150
|
-
vi.mocked(oauth.getValidatedIdTokenClaims).mockReturnValue({
|
|
151
|
-
sub: 'user-123',
|
|
152
|
-
});
|
|
153
|
-
const res = await app.request(`/callback?state=${state}&code=${code}`);
|
|
154
|
-
expect(res.status).toBe(302);
|
|
155
|
-
expect(res.headers.get('Location')).toBe('/dashboard');
|
|
156
|
-
});
|
|
157
|
-
it('rejects external returnTo and falls back to /', async () => {
|
|
158
|
-
const state = 'test-state-evil';
|
|
159
|
-
const code = 'test-code';
|
|
160
|
-
const codeVerifier = 'test-verifier';
|
|
161
|
-
const returnTo = 'https://evil.com/malicious';
|
|
162
|
-
await adapter.set(`pkce:${state}`, { codeVerifier, returnTo }, 600);
|
|
163
|
-
const res = await app.request(`/callback?state=${state}&code=${code}`);
|
|
164
|
-
expect(res.status).toBe(302);
|
|
165
|
-
expect(res.headers.get('Location')).toBe('/');
|
|
166
|
-
});
|
|
167
|
-
it('rejects protocol-relative returnTo (//) and falls back to /', async () => {
|
|
168
|
-
const state = 'test-state-proto';
|
|
169
|
-
const code = 'test-code';
|
|
170
|
-
const codeVerifier = 'test-verifier';
|
|
171
|
-
const returnTo = '//evil.com';
|
|
172
|
-
await adapter.set(`pkce:${state}`, { codeVerifier, returnTo }, 600);
|
|
173
|
-
const res = await app.request(`/callback?state=${state}&code=${code}`);
|
|
174
|
-
expect(res.status).toBe(302);
|
|
175
|
-
expect(res.headers.get('Location')).toBe('/');
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
describe('POST /logout', () => {
|
|
179
|
-
it('redirects to / if no logout URL can be determined', async () => {
|
|
180
|
-
auth.cache.cachedAS = null;
|
|
181
|
-
auth.cache.cacheExpiresAt = 0;
|
|
182
|
-
const mockAs = { issuer: config.issuer };
|
|
183
|
-
vi.mocked(oauth.discoveryRequest).mockResolvedValue({});
|
|
184
|
-
vi.mocked(oauth.processDiscoveryResponse).mockResolvedValue(mockAs);
|
|
185
|
-
const res = await app.request('/logout', { method: 'POST' });
|
|
186
|
-
expect(res.status).toBe(302);
|
|
187
|
-
expect(res.headers.get('Location')).toBe('/');
|
|
188
|
-
});
|
|
189
|
-
it('uses providerHints.logoutUrl if provided', async () => {
|
|
190
|
-
const customConfig = { ...config, providerHints: { logoutUrl: 'https://test.auth0.com/v2/logout' } };
|
|
191
|
-
const customAuth = createBezzie(customConfig);
|
|
192
|
-
const customApp = customAuth.routes();
|
|
193
|
-
const mockAs = { issuer: customConfig.issuer };
|
|
194
|
-
vi.mocked(oauth.discoveryRequest).mockResolvedValue({});
|
|
195
|
-
vi.mocked(oauth.processDiscoveryResponse).mockResolvedValue(mockAs);
|
|
196
|
-
const res = await customApp.request('/logout', { method: 'POST' });
|
|
197
|
-
expect(res.status).toBe(302);
|
|
198
|
-
const location = res.headers.get('Location');
|
|
199
|
-
expect(location).toContain('https://test.auth0.com/v2/logout');
|
|
200
|
-
expect(location).toContain(`client_id=${customConfig.clientId}`);
|
|
201
|
-
expect(location).toContain(`returnTo=${encodeURIComponent(customConfig.baseUrl)}`);
|
|
202
|
-
});
|
|
203
|
-
it('redirects to OIDC end_session_endpoint if available', async () => {
|
|
204
|
-
auth.cache.cachedAS = null;
|
|
205
|
-
auth.cache.cacheExpiresAt = 0;
|
|
206
|
-
const mockAs = {
|
|
207
|
-
issuer: config.issuer,
|
|
208
|
-
end_session_endpoint: `${config.issuer}/oidc/logout`
|
|
209
|
-
};
|
|
210
|
-
vi.mocked(oauth.discoveryRequest).mockResolvedValue({});
|
|
211
|
-
vi.mocked(oauth.processDiscoveryResponse).mockResolvedValue(mockAs);
|
|
212
|
-
const res = await app.request('/logout', { method: 'POST' });
|
|
213
|
-
expect(res.status).toBe(302);
|
|
214
|
-
const location = res.headers.get('Location');
|
|
215
|
-
expect(location).toContain(`${config.issuer}/oidc/logout`);
|
|
216
|
-
expect(location).toContain(`client_id=${config.clientId}`);
|
|
217
|
-
expect(location).toContain(`post_logout_redirect_uri=${encodeURIComponent(config.baseUrl)}`);
|
|
218
|
-
});
|
|
219
|
-
it('with valid session cookie - deletes session from adapter, clears cookie, and adds id_token_hint', async () => {
|
|
220
|
-
auth.cache.cachedAS = null;
|
|
221
|
-
auth.cache.cacheExpiresAt = 0;
|
|
222
|
-
const sessionId = 'test-session-id';
|
|
223
|
-
const idToken = 'mock-id-token';
|
|
224
|
-
await adapter.set(sessionId, {
|
|
225
|
-
accessToken: 'test',
|
|
226
|
-
refreshToken: 'refresh',
|
|
227
|
-
idToken,
|
|
228
|
-
expiresAt: Math.floor(Date.now() / 1000) + 3600,
|
|
229
|
-
createdAt: Math.floor(Date.now() / 1000),
|
|
230
|
-
user: { sub: 'user-123' },
|
|
231
|
-
}, 3600);
|
|
232
|
-
const mockAs = {
|
|
233
|
-
issuer: config.issuer,
|
|
234
|
-
end_session_endpoint: `${config.issuer}/logout`
|
|
235
|
-
};
|
|
236
|
-
vi.mocked(oauth.discoveryRequest).mockResolvedValue({});
|
|
237
|
-
vi.mocked(oauth.processDiscoveryResponse).mockResolvedValue(mockAs);
|
|
238
|
-
const res = await app.request('/logout', {
|
|
239
|
-
method: 'POST',
|
|
240
|
-
headers: {
|
|
241
|
-
Cookie: `__Host-session=${sessionId}`,
|
|
242
|
-
},
|
|
243
|
-
});
|
|
244
|
-
expect(res.status).toBe(302);
|
|
245
|
-
const location = res.headers.get('Location');
|
|
246
|
-
expect(location).toContain(`id_token_hint=${idToken}`);
|
|
247
|
-
// Check cookie cleared
|
|
248
|
-
const setCookie = res.headers.get('Set-Cookie');
|
|
249
|
-
expect(setCookie).toContain('__Host-session=;');
|
|
250
|
-
expect(setCookie).toContain('Max-Age=0');
|
|
251
|
-
// Check session deleted from adapter
|
|
252
|
-
expect(await adapter.get(sessionId)).toBeNull();
|
|
253
|
-
});
|
|
254
|
-
it('uses providerHints.logoutUrl and adds id_token_hint if session present', async () => {
|
|
255
|
-
const customConfig = { ...config, providerHints: { logoutUrl: 'https://test.auth0.com/v2/logout' } };
|
|
256
|
-
const customAuth = createBezzie(customConfig);
|
|
257
|
-
const customApp = customAuth.routes();
|
|
258
|
-
const sessionId = 'test-session-id';
|
|
259
|
-
const idToken = 'mock-id-token';
|
|
260
|
-
await adapter.set(sessionId, {
|
|
261
|
-
accessToken: 'test',
|
|
262
|
-
idToken,
|
|
263
|
-
expiresAt: Math.floor(Date.now() / 1000) + 3600,
|
|
264
|
-
createdAt: Math.floor(Date.now() / 1000),
|
|
265
|
-
user: { sub: 'user-123' },
|
|
266
|
-
}, 3600);
|
|
267
|
-
const mockAs = { issuer: customConfig.issuer };
|
|
268
|
-
vi.mocked(oauth.discoveryRequest).mockResolvedValue({});
|
|
269
|
-
vi.mocked(oauth.processDiscoveryResponse).mockResolvedValue(mockAs);
|
|
270
|
-
const res = await customApp.request('/logout', {
|
|
271
|
-
method: 'POST',
|
|
272
|
-
headers: {
|
|
273
|
-
Cookie: `__Host-session=${sessionId}`,
|
|
274
|
-
},
|
|
275
|
-
});
|
|
276
|
-
expect(res.status).toBe(302);
|
|
277
|
-
const location = res.headers.get('Location');
|
|
278
|
-
expect(location).toContain('https://test.auth0.com/v2/logout');
|
|
279
|
-
expect(location).toContain(`client_id=${customConfig.clientId}`);
|
|
280
|
-
expect(location).toContain(`id_token_hint=${idToken}`);
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
});
|
|
284
|
-
//# sourceMappingURL=routes.test.js.map
|