@geekmidas/auth 9.0.2 → 10.0.0-alpha.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/dist/{cacheTokenStorage-_tq4Kmhc.d.mts → cacheTokenStorage-DaqxdNxI.d.mts} +1 -1
- package/dist/cacheTokenStorage-DaqxdNxI.d.mts.map +1 -0
- package/dist/cacheTokenStorage.d.mts +1 -1
- package/dist/client.d.mts +1 -1
- package/dist/cookies-Bc6gUjb6.cjs +30 -0
- package/dist/cookies-Bc6gUjb6.cjs.map +1 -0
- package/dist/cookies-C80f8JtE.mjs +24 -0
- package/dist/cookies-C80f8JtE.mjs.map +1 -0
- package/dist/cookies.cjs +3 -0
- package/dist/cookies.d.cts +14 -0
- package/dist/cookies.d.cts.map +1 -0
- package/dist/cookies.d.mts +14 -0
- package/dist/cookies.d.mts.map +1 -0
- package/dist/cookies.mjs +3 -0
- package/dist/hono/jwt.cjs +4 -7
- package/dist/hono/jwt.cjs.map +1 -1
- package/dist/hono/jwt.d.cts.map +1 -1
- package/dist/hono/jwt.d.mts +1 -1
- package/dist/hono/jwt.d.mts.map +1 -1
- package/dist/hono/jwt.mjs +5 -7
- package/dist/hono/jwt.mjs.map +1 -1
- package/dist/hono/oidc.cjs +4 -7
- package/dist/hono/oidc.cjs.map +1 -1
- package/dist/hono/oidc.d.cts.map +1 -1
- package/dist/hono/oidc.d.mts +2 -2
- package/dist/hono/oidc.d.mts.map +1 -1
- package/dist/hono/oidc.mjs +5 -7
- package/dist/hono/oidc.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/{jwt-D88cPJyT.mjs → jwt-bZR2_t8F.mjs} +1 -1
- package/dist/{jwt-D88cPJyT.mjs.map → jwt-bZR2_t8F.mjs.map} +1 -1
- package/dist/{jwt-Bo_eACEi.cjs → jwt-clq6I6vG.cjs} +1 -1
- package/dist/{jwt-Bo_eACEi.cjs.map → jwt-clq6I6vG.cjs.map} +1 -1
- package/dist/{jwt-BqLlRkw-.d.mts → jwt-kejix7rd.d.mts} +1 -1
- package/dist/{jwt-BqLlRkw-.d.mts.map → jwt-kejix7rd.d.mts.map} +1 -1
- package/dist/jwt.cjs +1 -1
- package/dist/jwt.d.mts +1 -1
- package/dist/jwt.mjs +1 -1
- package/dist/lambda/jwt.cjs +4 -5
- package/dist/lambda/jwt.cjs.map +1 -1
- package/dist/lambda/jwt.d.cts.map +1 -1
- package/dist/lambda/jwt.d.mts +1 -1
- package/dist/lambda/jwt.d.mts.map +1 -1
- package/dist/lambda/jwt.mjs +5 -5
- package/dist/lambda/jwt.mjs.map +1 -1
- package/dist/lambda/oidc.cjs +4 -5
- package/dist/lambda/oidc.cjs.map +1 -1
- package/dist/lambda/oidc.d.cts.map +1 -1
- package/dist/lambda/oidc.d.mts +2 -2
- package/dist/lambda/oidc.d.mts.map +1 -1
- package/dist/lambda/oidc.mjs +5 -5
- package/dist/lambda/oidc.mjs.map +1 -1
- package/dist/{oidc-KA30gMlx.mjs → oidc-BYHREHir.mjs} +1 -1
- package/dist/{oidc-KA30gMlx.mjs.map → oidc-BYHREHir.mjs.map} +1 -1
- package/dist/{oidc-DTRgBBl6.d.mts → oidc-Ca7GYwmM.d.mts} +2 -2
- package/dist/{oidc-DTRgBBl6.d.mts.map → oidc-Ca7GYwmM.d.mts.map} +1 -1
- package/dist/{oidc-C0KyYaAK.cjs → oidc-jdMfVyyC.cjs} +1 -1
- package/dist/{oidc-C0KyYaAK.cjs.map → oidc-jdMfVyyC.cjs.map} +1 -1
- package/dist/oidc.cjs +1 -1
- package/dist/oidc.d.mts +2 -2
- package/dist/oidc.mjs +1 -1
- package/dist/server.cjs +1 -1
- package/dist/server.d.mts +2 -2
- package/dist/server.mjs +1 -1
- package/dist/{tokenManager-Ci2Tgxp8.mjs → tokenManager-BbylTW7F.mjs} +1 -1
- package/dist/{tokenManager-Ci2Tgxp8.mjs.map → tokenManager-BbylTW7F.mjs.map} +1 -1
- package/dist/{tokenManager-RrwjL0y-.d.mts → tokenManager-CosB7J0i.d.mts} +1 -1
- package/dist/{tokenManager-RrwjL0y-.d.mts.map → tokenManager-CosB7J0i.d.mts.map} +1 -1
- package/dist/{tokenManager-CvEMgxOp.cjs → tokenManager-PQ-OI_NU.cjs} +1 -1
- package/dist/{tokenManager-CvEMgxOp.cjs.map → tokenManager-PQ-OI_NU.cjs.map} +1 -1
- package/dist/tokenManager.cjs +1 -1
- package/dist/tokenManager.d.mts +1 -1
- package/dist/tokenManager.mjs +1 -1
- package/package.json +6 -3
- package/CHANGELOG.md +0 -60
- package/dist/cacheTokenStorage-_tq4Kmhc.d.mts.map +0 -1
- package/src/__tests__/cacheTokenStorage.spec.ts +0 -213
- package/src/__tests__/client.spec.ts +0 -465
- package/src/__tests__/hono-jwt.spec.ts +0 -232
- package/src/__tests__/hono-oidc.spec.ts +0 -605
- package/src/__tests__/jwt.spec.ts +0 -197
- package/src/__tests__/lambda-jwt.spec.ts +0 -278
- package/src/__tests__/lambda-oidc.spec.ts +0 -624
- package/src/__tests__/oidc.spec.ts +0 -405
- package/src/__tests__/tokenManager.spec.ts +0 -259
- package/src/cacheTokenStorage.ts +0 -43
- package/src/client.ts +0 -220
- package/src/hono/jwt.ts +0 -142
- package/src/hono/oidc.ts +0 -170
- package/src/index.ts +0 -3
- package/src/jwt.ts +0 -106
- package/src/lambda/jwt.ts +0 -210
- package/src/lambda/oidc.ts +0 -203
- package/src/oidc.ts +0 -156
- package/src/server.ts +0 -8
- package/src/tokenManager.ts +0 -106
- package/tsconfig.json +0 -10
- package/tsdown.config.ts +0 -3
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import * as jose from 'jose';
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import { decodeJwt, JwtVerifier } from '../jwt';
|
|
4
|
-
|
|
5
|
-
const TEST_SECRET = 'super-secret-key-for-testing-only-32chars';
|
|
6
|
-
|
|
7
|
-
async function createTestToken(
|
|
8
|
-
claims: Record<string, unknown> = {},
|
|
9
|
-
options: {
|
|
10
|
-
secret?: string;
|
|
11
|
-
expiresIn?: string;
|
|
12
|
-
issuer?: string;
|
|
13
|
-
audience?: string;
|
|
14
|
-
} = {},
|
|
15
|
-
) {
|
|
16
|
-
const secret = new TextEncoder().encode(options.secret ?? TEST_SECRET);
|
|
17
|
-
const jwt = new jose.SignJWT({ sub: 'user-123', ...claims })
|
|
18
|
-
.setProtectedHeader({ alg: 'HS256' })
|
|
19
|
-
.setIssuedAt();
|
|
20
|
-
|
|
21
|
-
if (options.expiresIn) {
|
|
22
|
-
jwt.setExpirationTime(options.expiresIn);
|
|
23
|
-
} else {
|
|
24
|
-
jwt.setExpirationTime('1h');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (options.issuer) {
|
|
28
|
-
jwt.setIssuer(options.issuer);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (options.audience) {
|
|
32
|
-
jwt.setAudience(options.audience);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return await jwt.sign(secret);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
describe('JwtVerifier', () => {
|
|
39
|
-
describe('with secret', () => {
|
|
40
|
-
it('should verify a valid token', async () => {
|
|
41
|
-
const verifier = new JwtVerifier({ secret: TEST_SECRET });
|
|
42
|
-
const token = await createTestToken();
|
|
43
|
-
|
|
44
|
-
const claims = await verifier.verify(token);
|
|
45
|
-
|
|
46
|
-
expect(claims.sub).toBe('user-123');
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should throw for invalid token', async () => {
|
|
50
|
-
const verifier = new JwtVerifier({ secret: TEST_SECRET });
|
|
51
|
-
|
|
52
|
-
await expect(verifier.verify('invalid-token')).rejects.toThrow();
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('should throw for wrong secret', async () => {
|
|
56
|
-
const verifier = new JwtVerifier({ secret: TEST_SECRET });
|
|
57
|
-
const token = await createTestToken(
|
|
58
|
-
{},
|
|
59
|
-
{ secret: 'wrong-secret-key-32-chars-long!!' },
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
await expect(verifier.verify(token)).rejects.toThrow();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('should throw for expired token', async () => {
|
|
66
|
-
const verifier = new JwtVerifier({ secret: TEST_SECRET });
|
|
67
|
-
const token = await createTestToken({}, { expiresIn: '-1h' });
|
|
68
|
-
|
|
69
|
-
await expect(verifier.verify(token)).rejects.toThrow();
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('should validate issuer when configured', async () => {
|
|
73
|
-
const verifier = new JwtVerifier({
|
|
74
|
-
secret: TEST_SECRET,
|
|
75
|
-
issuer: 'my-app',
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
const validToken = await createTestToken({}, { issuer: 'my-app' });
|
|
79
|
-
const invalidToken = await createTestToken({}, { issuer: 'other-app' });
|
|
80
|
-
|
|
81
|
-
await expect(verifier.verify(validToken)).resolves.toBeDefined();
|
|
82
|
-
await expect(verifier.verify(invalidToken)).rejects.toThrow();
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('should validate audience when configured', async () => {
|
|
86
|
-
const verifier = new JwtVerifier({
|
|
87
|
-
secret: TEST_SECRET,
|
|
88
|
-
audience: 'my-api',
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
const validToken = await createTestToken({}, { audience: 'my-api' });
|
|
92
|
-
const invalidToken = await createTestToken({}, { audience: 'other-api' });
|
|
93
|
-
|
|
94
|
-
await expect(verifier.verify(validToken)).resolves.toBeDefined();
|
|
95
|
-
await expect(verifier.verify(invalidToken)).rejects.toThrow();
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
describe('verifyOrNull', () => {
|
|
100
|
-
it('should return claims for valid token', async () => {
|
|
101
|
-
const verifier = new JwtVerifier({ secret: TEST_SECRET });
|
|
102
|
-
const token = await createTestToken();
|
|
103
|
-
|
|
104
|
-
const claims = await verifier.verifyOrNull(token);
|
|
105
|
-
|
|
106
|
-
expect(claims).not.toBeNull();
|
|
107
|
-
expect(claims?.sub).toBe('user-123');
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('should return null for invalid token', async () => {
|
|
111
|
-
const verifier = new JwtVerifier({ secret: TEST_SECRET });
|
|
112
|
-
|
|
113
|
-
const claims = await verifier.verifyOrNull('invalid-token');
|
|
114
|
-
|
|
115
|
-
expect(claims).toBeNull();
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it('should return null for expired token', async () => {
|
|
119
|
-
const verifier = new JwtVerifier({ secret: TEST_SECRET });
|
|
120
|
-
const token = await createTestToken({}, { expiresIn: '-1h' });
|
|
121
|
-
|
|
122
|
-
const claims = await verifier.verifyOrNull(token);
|
|
123
|
-
|
|
124
|
-
expect(claims).toBeNull();
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
describe('custom claims', () => {
|
|
129
|
-
interface CustomClaims {
|
|
130
|
-
sub?: string;
|
|
131
|
-
role: string;
|
|
132
|
-
permissions: string[];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
it('should return typed claims', async () => {
|
|
136
|
-
const verifier = new JwtVerifier<CustomClaims>({ secret: TEST_SECRET });
|
|
137
|
-
const token = await createTestToken({
|
|
138
|
-
role: 'admin',
|
|
139
|
-
permissions: ['read', 'write'],
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
const claims = await verifier.verify(token);
|
|
143
|
-
|
|
144
|
-
expect(claims.role).toBe('admin');
|
|
145
|
-
expect(claims.permissions).toEqual(['read', 'write']);
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
describe('clearCache', () => {
|
|
151
|
-
it('should clear the JWKS cache', () => {
|
|
152
|
-
const verifier = new JwtVerifier({ secret: TEST_SECRET });
|
|
153
|
-
|
|
154
|
-
// Call clearCache - should not throw
|
|
155
|
-
verifier.clearCache();
|
|
156
|
-
|
|
157
|
-
// Verify the method exists and can be called
|
|
158
|
-
expect(verifier.clearCache).toBeDefined();
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('should allow re-verification after clearing cache', async () => {
|
|
162
|
-
const verifier = new JwtVerifier({ secret: TEST_SECRET });
|
|
163
|
-
const token = await createTestToken();
|
|
164
|
-
|
|
165
|
-
const claims1 = await verifier.verify(token);
|
|
166
|
-
verifier.clearCache();
|
|
167
|
-
const claims2 = await verifier.verify(token);
|
|
168
|
-
|
|
169
|
-
expect(claims1.sub).toBe(claims2.sub);
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
describe('decodeJwt', () => {
|
|
174
|
-
it('should decode token without verification', async () => {
|
|
175
|
-
const token = await createTestToken({ custom: 'data' });
|
|
176
|
-
|
|
177
|
-
const claims = decodeJwt(token);
|
|
178
|
-
|
|
179
|
-
expect(claims.sub).toBe('user-123');
|
|
180
|
-
expect(claims).toHaveProperty('custom', 'data');
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it('should decode token even with wrong secret', async () => {
|
|
184
|
-
const token = await createTestToken(
|
|
185
|
-
{},
|
|
186
|
-
{ secret: 'any-secret-32-characters-long!!' },
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
const claims = decodeJwt(token);
|
|
190
|
-
|
|
191
|
-
expect(claims.sub).toBe('user-123');
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('should throw for malformed token', () => {
|
|
195
|
-
expect(() => decodeJwt('not.a.valid.jwt')).toThrow();
|
|
196
|
-
});
|
|
197
|
-
});
|
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
APIGatewayRequestAuthorizerEvent,
|
|
3
|
-
APIGatewayTokenAuthorizerEvent,
|
|
4
|
-
Context as LambdaContext,
|
|
5
|
-
} from 'aws-lambda';
|
|
6
|
-
import * as jose from 'jose';
|
|
7
|
-
import { describe, expect, it } from 'vitest';
|
|
8
|
-
import { JwtAuthorizer } from '../lambda/jwt';
|
|
9
|
-
|
|
10
|
-
const TEST_SECRET = 'super-secret-key-for-testing-only-32chars';
|
|
11
|
-
const TEST_METHOD_ARN =
|
|
12
|
-
'arn:aws:execute-api:us-east-1:123456789:api-id/stage/GET/resource';
|
|
13
|
-
|
|
14
|
-
async function createTestToken(
|
|
15
|
-
claims: Record<string, unknown> = {},
|
|
16
|
-
secret = TEST_SECRET,
|
|
17
|
-
) {
|
|
18
|
-
const secretKey = new TextEncoder().encode(secret);
|
|
19
|
-
return await new jose.SignJWT({ sub: 'user-123', ...claims })
|
|
20
|
-
.setProtectedHeader({ alg: 'HS256' })
|
|
21
|
-
.setIssuedAt()
|
|
22
|
-
.setExpirationTime('1h')
|
|
23
|
-
.sign(secretKey);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function createTokenEvent(
|
|
27
|
-
token: string,
|
|
28
|
-
methodArn = TEST_METHOD_ARN,
|
|
29
|
-
): APIGatewayTokenAuthorizerEvent {
|
|
30
|
-
return {
|
|
31
|
-
type: 'TOKEN',
|
|
32
|
-
authorizationToken: `Bearer ${token}`,
|
|
33
|
-
methodArn,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function createRequestEvent(
|
|
38
|
-
headers: Record<string, string> = {},
|
|
39
|
-
methodArn = TEST_METHOD_ARN,
|
|
40
|
-
): APIGatewayRequestAuthorizerEvent {
|
|
41
|
-
return {
|
|
42
|
-
type: 'REQUEST',
|
|
43
|
-
methodArn,
|
|
44
|
-
headers,
|
|
45
|
-
multiValueHeaders: {},
|
|
46
|
-
pathParameters: null,
|
|
47
|
-
queryStringParameters: null,
|
|
48
|
-
multiValueQueryStringParameters: null,
|
|
49
|
-
stageVariables: null,
|
|
50
|
-
requestContext: {} as any,
|
|
51
|
-
resource: '',
|
|
52
|
-
path: '',
|
|
53
|
-
httpMethod: 'GET',
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const mockLambdaContext = {} as LambdaContext;
|
|
58
|
-
|
|
59
|
-
describe('JwtAuthorizer', () => {
|
|
60
|
-
describe('tokenHandler()', () => {
|
|
61
|
-
it('should allow valid token', async () => {
|
|
62
|
-
const authorizer = new JwtAuthorizer({
|
|
63
|
-
config: { secret: TEST_SECRET },
|
|
64
|
-
});
|
|
65
|
-
const handler = authorizer.tokenHandler();
|
|
66
|
-
|
|
67
|
-
const token = await createTestToken();
|
|
68
|
-
const event = createTokenEvent(token);
|
|
69
|
-
|
|
70
|
-
const result = await handler(event, mockLambdaContext);
|
|
71
|
-
|
|
72
|
-
expect(result.policyDocument.Statement[0].Effect).toBe('Allow');
|
|
73
|
-
expect(result.principalId).toBe('user-123');
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('should deny invalid token', async () => {
|
|
77
|
-
const authorizer = new JwtAuthorizer({
|
|
78
|
-
config: { secret: TEST_SECRET },
|
|
79
|
-
});
|
|
80
|
-
const handler = authorizer.tokenHandler();
|
|
81
|
-
|
|
82
|
-
const event = createTokenEvent('invalid-token');
|
|
83
|
-
|
|
84
|
-
const result = await handler(event, mockLambdaContext);
|
|
85
|
-
|
|
86
|
-
expect(result.policyDocument.Statement[0].Effect).toBe('Deny');
|
|
87
|
-
expect(result.principalId).toBe('unauthorized');
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('should use wildcard resource by default', async () => {
|
|
91
|
-
const authorizer = new JwtAuthorizer({
|
|
92
|
-
config: { secret: TEST_SECRET },
|
|
93
|
-
});
|
|
94
|
-
const handler = authorizer.tokenHandler();
|
|
95
|
-
|
|
96
|
-
const token = await createTestToken();
|
|
97
|
-
const event = createTokenEvent(token);
|
|
98
|
-
|
|
99
|
-
const result = await handler(event, mockLambdaContext);
|
|
100
|
-
|
|
101
|
-
expect(result.policyDocument.Statement[0].Resource).toBe(
|
|
102
|
-
'arn:aws:execute-api:us-east-1:123456789:api-id/stage/*',
|
|
103
|
-
);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it('should use exact resource when wildcardResource is false', async () => {
|
|
107
|
-
const authorizer = new JwtAuthorizer({
|
|
108
|
-
config: { secret: TEST_SECRET },
|
|
109
|
-
wildcardResource: false,
|
|
110
|
-
});
|
|
111
|
-
const handler = authorizer.tokenHandler();
|
|
112
|
-
|
|
113
|
-
const token = await createTestToken();
|
|
114
|
-
const event = createTokenEvent(token);
|
|
115
|
-
|
|
116
|
-
const result = await handler(event, mockLambdaContext);
|
|
117
|
-
|
|
118
|
-
expect(result.policyDocument.Statement[0].Resource).toBe(TEST_METHOD_ARN);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it('should use custom getPrincipalId', async () => {
|
|
122
|
-
const authorizer = new JwtAuthorizer({
|
|
123
|
-
config: { secret: TEST_SECRET },
|
|
124
|
-
getPrincipalId: (claims) => `custom-${claims.sub}`,
|
|
125
|
-
});
|
|
126
|
-
const handler = authorizer.tokenHandler();
|
|
127
|
-
|
|
128
|
-
const token = await createTestToken();
|
|
129
|
-
const event = createTokenEvent(token);
|
|
130
|
-
|
|
131
|
-
const result = await handler(event, mockLambdaContext);
|
|
132
|
-
|
|
133
|
-
expect(result.principalId).toBe('custom-user-123');
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('should include context from getContext', async () => {
|
|
137
|
-
const authorizer = new JwtAuthorizer({
|
|
138
|
-
config: { secret: TEST_SECRET },
|
|
139
|
-
getContext: (claims) => ({
|
|
140
|
-
userId: claims.sub!,
|
|
141
|
-
role: 'admin',
|
|
142
|
-
}),
|
|
143
|
-
});
|
|
144
|
-
const handler = authorizer.tokenHandler();
|
|
145
|
-
|
|
146
|
-
const token = await createTestToken();
|
|
147
|
-
const event = createTokenEvent(token);
|
|
148
|
-
|
|
149
|
-
const result = await handler(event, mockLambdaContext);
|
|
150
|
-
|
|
151
|
-
expect(result.context).toEqual({
|
|
152
|
-
userId: 'user-123',
|
|
153
|
-
role: 'admin',
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it('should deny when custom authorize returns false', async () => {
|
|
158
|
-
const authorizer = new JwtAuthorizer({
|
|
159
|
-
config: { secret: TEST_SECRET },
|
|
160
|
-
authorize: (claims) => claims.sub === 'admin',
|
|
161
|
-
});
|
|
162
|
-
const handler = authorizer.tokenHandler();
|
|
163
|
-
|
|
164
|
-
const token = await createTestToken();
|
|
165
|
-
const event = createTokenEvent(token);
|
|
166
|
-
|
|
167
|
-
const result = await handler(event, mockLambdaContext);
|
|
168
|
-
|
|
169
|
-
expect(result.policyDocument.Statement[0].Effect).toBe('Deny');
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it('should allow when custom authorize returns true', async () => {
|
|
173
|
-
const authorizer = new JwtAuthorizer({
|
|
174
|
-
config: { secret: TEST_SECRET },
|
|
175
|
-
authorize: (claims) => claims.sub === 'user-123',
|
|
176
|
-
});
|
|
177
|
-
const handler = authorizer.tokenHandler();
|
|
178
|
-
|
|
179
|
-
const token = await createTestToken();
|
|
180
|
-
const event = createTokenEvent(token);
|
|
181
|
-
|
|
182
|
-
const result = await handler(event, mockLambdaContext);
|
|
183
|
-
|
|
184
|
-
expect(result.policyDocument.Statement[0].Effect).toBe('Allow');
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
it('should handle token without Bearer prefix', async () => {
|
|
188
|
-
const authorizer = new JwtAuthorizer({
|
|
189
|
-
config: { secret: TEST_SECRET },
|
|
190
|
-
});
|
|
191
|
-
const handler = authorizer.tokenHandler();
|
|
192
|
-
|
|
193
|
-
const token = await createTestToken();
|
|
194
|
-
const event: APIGatewayTokenAuthorizerEvent = {
|
|
195
|
-
type: 'TOKEN',
|
|
196
|
-
authorizationToken: token, // No Bearer prefix
|
|
197
|
-
methodArn: TEST_METHOD_ARN,
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
const result = await handler(event, mockLambdaContext);
|
|
201
|
-
|
|
202
|
-
expect(result.policyDocument.Statement[0].Effect).toBe('Allow');
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
describe('requestHandler()', () => {
|
|
207
|
-
it('should allow valid token from Authorization header', async () => {
|
|
208
|
-
const authorizer = new JwtAuthorizer({
|
|
209
|
-
config: { secret: TEST_SECRET },
|
|
210
|
-
});
|
|
211
|
-
const handler = authorizer.requestHandler();
|
|
212
|
-
|
|
213
|
-
const token = await createTestToken();
|
|
214
|
-
const event = createRequestEvent({ Authorization: `Bearer ${token}` });
|
|
215
|
-
|
|
216
|
-
const result = await handler(event, mockLambdaContext);
|
|
217
|
-
|
|
218
|
-
expect(result.policyDocument.Statement[0].Effect).toBe('Allow');
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
it('should deny when no token provided', async () => {
|
|
222
|
-
const authorizer = new JwtAuthorizer({
|
|
223
|
-
config: { secret: TEST_SECRET },
|
|
224
|
-
});
|
|
225
|
-
const handler = authorizer.requestHandler();
|
|
226
|
-
|
|
227
|
-
const event = createRequestEvent({});
|
|
228
|
-
|
|
229
|
-
const result = await handler(event, mockLambdaContext);
|
|
230
|
-
|
|
231
|
-
expect(result.policyDocument.Statement[0].Effect).toBe('Deny');
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
it('should extract token from custom header', async () => {
|
|
235
|
-
const authorizer = new JwtAuthorizer({
|
|
236
|
-
config: { secret: TEST_SECRET },
|
|
237
|
-
extraction: { headerName: 'x-api-token', tokenPrefix: '' },
|
|
238
|
-
});
|
|
239
|
-
const handler = authorizer.requestHandler();
|
|
240
|
-
|
|
241
|
-
const token = await createTestToken();
|
|
242
|
-
const event = createRequestEvent({ 'x-api-token': token });
|
|
243
|
-
|
|
244
|
-
const result = await handler(event, mockLambdaContext);
|
|
245
|
-
|
|
246
|
-
expect(result.policyDocument.Statement[0].Effect).toBe('Allow');
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
it('should extract token from cookie', async () => {
|
|
250
|
-
const authorizer = new JwtAuthorizer({
|
|
251
|
-
config: { secret: TEST_SECRET },
|
|
252
|
-
extraction: { cookieName: 'session' },
|
|
253
|
-
});
|
|
254
|
-
const handler = authorizer.requestHandler();
|
|
255
|
-
|
|
256
|
-
const token = await createTestToken();
|
|
257
|
-
const event = createRequestEvent({ cookie: `session=${token}` });
|
|
258
|
-
|
|
259
|
-
const result = await handler(event, mockLambdaContext);
|
|
260
|
-
|
|
261
|
-
expect(result.policyDocument.Statement[0].Effect).toBe('Allow');
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it('should handle case-insensitive headers', async () => {
|
|
265
|
-
const authorizer = new JwtAuthorizer({
|
|
266
|
-
config: { secret: TEST_SECRET },
|
|
267
|
-
});
|
|
268
|
-
const handler = authorizer.requestHandler();
|
|
269
|
-
|
|
270
|
-
const token = await createTestToken();
|
|
271
|
-
const event = createRequestEvent({ authorization: `Bearer ${token}` });
|
|
272
|
-
|
|
273
|
-
const result = await handler(event, mockLambdaContext);
|
|
274
|
-
|
|
275
|
-
expect(result.policyDocument.Statement[0].Effect).toBe('Allow');
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
});
|