|
1 | 1 | import 'dotenv/config'; |
2 | | -import { jwtVerify, decodeJwt, errors, importSPKI } from 'jose'; |
| 2 | +import { decodeJwt } from 'jose'; |
3 | 3 |
|
4 | 4 |
|
5 | 5 | export async function parseAuthToken(header: string) { |
6 | 6 | if (!header) { |
7 | 7 | console.error('No auth token provided to parse'); |
8 | | - return null; |
| 8 | + return { email: null, roles: [] }; |
9 | 9 | } |
10 | 10 |
|
11 | | - const tokenContent = await getDecodedJwt(header, false); |
12 | | - |
13 | | - if (!tokenContent) { |
14 | | - return null; |
| 11 | + // Decode without verification since we're using auth-at-the-edge and can trust all traffic |
| 12 | + let tokenContent; |
| 13 | + try { |
| 14 | + tokenContent = decodeJwt(header); |
| 15 | + } catch(error) { |
| 16 | + console.error('Malformed JWT during decoding: ' + header, error); |
| 17 | + return { email: null, roles: [] }; |
15 | 18 | } |
16 | 19 |
|
17 | | - const email = tokenContent.email; |
| 20 | + const email = tokenContent.email as string | undefined; |
18 | 21 | if (!email) { |
19 | 22 | console.error('No email found in token'); |
20 | 23 | return null; |
21 | 24 | } |
22 | 25 |
|
23 | | - const realmAccess = tokenContent.realm_access; |
| 26 | + const realmAccess = tokenContent.realm_access as { roles?: string[] } | undefined; |
24 | 27 | if (!realmAccess) { |
25 | 28 | console.error('No realm access information found in token'); |
26 | | - return null; |
| 29 | + return { email: null, roles: [] }; |
27 | 30 | } |
28 | 31 |
|
29 | | - const roles = tokenContent.realm_access.roles || []; |
| 32 | + const roles = realmAccess.roles || []; |
30 | 33 | // console.debug(`Roles found for user ${email}: ${roles}`); |
31 | 34 | return { |
32 | 35 | email, |
33 | 36 | roles, |
34 | 37 | }; |
35 | 38 | } |
36 | 39 |
|
37 | | -async function getDecodedJwt(header: string, verifyJwtSource: boolean) { |
38 | | - let decodedToken = null; |
39 | | - |
40 | | - try { |
41 | | - if (verifyJwtSource) { |
42 | | - const publicKeyEncoded = process.env.AUTH_PROVIDER_PUBLIC_KEY!; // This is passed into the environment by ECS |
43 | | - const pemPublicKey = convertToPemPublicKey(publicKeyEncoded); |
44 | | - const publicKey = await importSPKI(pemPublicKey, 'RS256'); |
45 | | - |
46 | | - try { |
47 | | - // Verify with signature |
48 | | - const { payload } = await jwtVerify(header, publicKey, { |
49 | | - algorithms: ['RS256'], |
50 | | - audience: 'account', |
51 | | - }); |
52 | | - |
53 | | - decodedToken = payload; |
54 | | - } catch(error) { |
55 | | - if (error instanceof errors.JWTExpired) { |
56 | | - console.error('JWT has expired:', error.message); |
57 | | - return null; |
58 | | - } else if (error instanceof errors.JWTInvalid) { |
59 | | - console.error('Malformed JWT:', error.message); |
60 | | - return null; |
61 | | - } |
62 | | - console.error('Unexpected JWT verification error:', error); |
63 | | - return null; |
64 | | - } |
65 | | - } else { |
66 | | - // Decode without verification |
67 | | - try { |
68 | | - decodedToken = decodeJwt(header); |
69 | | - } catch(error) { |
70 | | - console.error('Malformed JWT during decoding:', error); |
71 | | - return null; |
72 | | - } |
73 | | - } |
74 | | - return decodedToken; |
75 | | - } catch(error) { |
76 | | - console.error('Unexpected error in getDecodedJwt:', error); |
77 | | - return null; |
78 | | - } |
79 | | -} |
80 | | - |
81 | | -function convertToPemPublicKey(keyBase64: string): string { |
82 | | - return `-----BEGIN PUBLIC KEY-----\n${keyBase64}\n-----END PUBLIC KEY-----`; |
83 | | -} |
84 | 40 |
|
85 | 41 | /* |
86 | 42 | *export async function getServerSideDecodedToken() { |
|
0 commit comments