|
1 | | -import { defineEventHandler, getHeader } from 'h3'; |
2 | | -import jwt from 'jsonwebtoken'; |
3 | | -import axios from 'axios'; |
4 | | -import jwkToPem from 'jwk-to-pem'; |
5 | 1 | import crypto from 'crypto'; |
| 2 | +import axios from 'axios'; |
| 3 | +import { defineEventHandler, getHeader } from "h3"; |
| 4 | +import jwt from "jsonwebtoken"; |
| 5 | +import jwkToPem from "jwk-to-pem"; |
6 | 6 |
|
7 | | -const GOOGLE_JWKS_URL = 'https://www.googleapis.com/oauth2/v3/certs'; |
| 7 | +const GOOGLE_JWKS_URL = "https://www.googleapis.com/oauth2/v3/certs"; |
8 | 8 | const GOOGLE_ISSUERS = [ |
9 | | - 'https://accounts.google.com', |
10 | | - 'accounts.google.com', |
| 9 | + "https://accounts.google.com", |
| 10 | + "accounts.google.com", |
11 | 11 | ]; |
12 | | -const SALT_ENTROPY = process.env.SALT_ENTROPY || 'entropy'; |
| 12 | +const SALT_ENTROPY = process.env.SALT_ENTROPY || "entropy"; |
13 | 13 |
|
14 | 14 | async function getGooglePublicKey(kid: string) { |
15 | 15 | const { data } = await axios.get(GOOGLE_JWKS_URL); |
16 | 16 | const jwk = data.keys.find((key: any) => key.kid === kid); |
17 | 17 |
|
18 | 18 | if (!jwk) { |
19 | | - throw new Error('Public key not found'); |
| 19 | + throw new Error("Public key not found"); |
20 | 20 | } |
21 | 21 |
|
22 | 22 | return jwkToPem(jwk); |
23 | 23 | } |
24 | 24 |
|
25 | 25 | export default defineEventHandler(async (event) => { |
26 | | - const authHeader = getHeader(event, 'Authorization'); |
| 26 | + const authHeader = getHeader(event, "Authorization"); |
27 | 27 |
|
28 | | - if (!authHeader || !authHeader.startsWith('Bearer ')) { |
| 28 | + if (!authHeader || !authHeader.startsWith("Bearer ")) { |
29 | 29 | throw createError({ |
30 | 30 | statusCode: 401, |
31 | | - message: 'Unauthorized - Missing or invalid token', |
| 31 | + message: "Unauthorized - Missing or invalid token", |
32 | 32 | }); |
33 | 33 | } |
34 | 34 |
|
35 | | - const token = authHeader.split(' ')[1]; |
| 35 | + const token = authHeader.split(" ")[1]; |
36 | 36 |
|
37 | 37 | try { |
38 | 38 | const decoded = jwt.decode(token, { complete: true }) as any; |
39 | 39 | if (!decoded?.payload?.iss || !GOOGLE_ISSUERS.includes(decoded.payload.iss)) { |
40 | | - throw new Error('Invalid issuer'); |
| 40 | + throw new Error("Invalid issuer"); |
41 | 41 | } |
42 | 42 |
|
43 | 43 | if (!decoded?.header?.kid) { |
44 | | - throw new Error('JWT missing "kid"'); |
| 44 | + throw new Error("JWT missing \"kid\""); |
45 | 45 | } |
46 | 46 |
|
47 | 47 | const publicKey = await getGooglePublicKey(decoded.header.kid); |
48 | 48 |
|
49 | 49 | const verifiedToken = jwt.verify(token, publicKey, { |
50 | | - algorithms: ['RS256'], |
| 50 | + algorithms: ["RS256"], |
51 | 51 | }); |
52 | 52 |
|
53 | 53 | const iss = verifiedToken.iss; |
54 | 54 | const aud = verifiedToken.aud; |
55 | 55 | const sub = verifiedToken.sub; |
56 | 56 |
|
57 | | - const data = { iss, aud, sub , entropy: SALT_ENTROPY }; |
58 | | - const hash = crypto.createHash('sha256').update(JSON.stringify(data)).digest('hex'); |
| 57 | + const data = { iss, aud, sub, entropy: SALT_ENTROPY }; |
| 58 | + const hash = crypto.createHash("sha256").update(JSON.stringify(data)).digest("hex"); |
59 | 59 |
|
60 | 60 | return { salt: hash }; |
61 | 61 | } catch (error) { |
62 | 62 | throw createError({ |
63 | 63 | statusCode: 401, |
64 | | - message: 'Unauthorized - Invalid token or verification failed', |
| 64 | + message: "Unauthorized - Invalid token or verification failed", |
65 | 65 | }); |
66 | 66 | } |
67 | 67 | }); |
0 commit comments