@zodic/shared 0.0.103 → 0.0.105
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/package.json +1 -1
- package/utils/index.ts +33 -41
package/package.json
CHANGED
package/utils/index.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { jwtVerify } from 'jose';
|
|
2
|
-
import { webcrypto } from 'node:crypto';
|
|
3
2
|
import { AuthCtx, Gender, JWKS, VALID_GENDERS_ARRAY } from '../types';
|
|
4
3
|
|
|
5
4
|
export const verifyToken = async (
|
|
@@ -10,6 +9,12 @@ export const verifyToken = async (
|
|
|
10
9
|
const audience = c.env.GOOGLE_OAUTH_CLIENT_ID;
|
|
11
10
|
const issuer = 'https://accounts.google.com';
|
|
12
11
|
|
|
12
|
+
console.log('🔍 Verifying JWT...');
|
|
13
|
+
console.log('🔹 Received Token:', token);
|
|
14
|
+
console.log('🔹 JWT Secret:', jwtSecret ? '✅ Exists' : '❌ Missing');
|
|
15
|
+
console.log('🔹 Audience:', audience);
|
|
16
|
+
console.log('🔹 Issuer:', issuer);
|
|
17
|
+
|
|
13
18
|
if (!jwtSecret) throw new Error('JWT Secret is not defined in the environment');
|
|
14
19
|
|
|
15
20
|
try {
|
|
@@ -18,19 +23,27 @@ export const verifyToken = async (
|
|
|
18
23
|
Buffer.from(token.split('.')[0], 'base64').toString('utf8')
|
|
19
24
|
);
|
|
20
25
|
|
|
26
|
+
console.log('🔍 Decoded JWT Header:', decodedHeader);
|
|
27
|
+
|
|
21
28
|
if (decodedHeader.alg.startsWith('RS')) {
|
|
22
|
-
|
|
29
|
+
console.log('🔹 Google OAuth Token Detected');
|
|
30
|
+
|
|
31
|
+
// 🔹 Verify with Google Public Keys
|
|
23
32
|
const kid = decodedHeader.kid;
|
|
33
|
+
console.log('🔹 Extracted Key ID (kid):', kid);
|
|
24
34
|
|
|
25
35
|
const googleKeysResponse = await fetch(
|
|
26
36
|
'https://www.googleapis.com/oauth2/v3/certs'
|
|
27
37
|
);
|
|
28
38
|
const googleKeys = (await googleKeysResponse.json()) as JWKS;
|
|
39
|
+
console.log('🔍 Fetched Google Public Keys:', googleKeys);
|
|
40
|
+
|
|
41
|
+
const key = googleKeys.keys.find((k) => k.kid === kid);
|
|
42
|
+
if (!key) throw new Error('❌ Google public key not found');
|
|
29
43
|
|
|
30
|
-
|
|
31
|
-
if (!key) throw new Error('Google public key not found');
|
|
44
|
+
console.log('🔹 Matching Google Key Found:', key);
|
|
32
45
|
|
|
33
|
-
const publicKey = await
|
|
46
|
+
const publicKey = await crypto.subtle.importKey(
|
|
34
47
|
'jwk',
|
|
35
48
|
key,
|
|
36
49
|
{ name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' },
|
|
@@ -38,20 +51,26 @@ export const verifyToken = async (
|
|
|
38
51
|
['verify']
|
|
39
52
|
);
|
|
40
53
|
|
|
54
|
+
console.log('🔍 Imported Google Public Key');
|
|
55
|
+
|
|
41
56
|
const { payload } = await jwtVerify(token, publicKey, {
|
|
42
57
|
audience,
|
|
43
58
|
issuer,
|
|
44
59
|
});
|
|
45
60
|
|
|
61
|
+
console.log('✅ Google JWT Verified! Payload:', payload);
|
|
62
|
+
|
|
46
63
|
if (!payload.sub) {
|
|
47
|
-
throw new Error('Google token is missing required "sub" claim');
|
|
64
|
+
throw new Error('❌ Google token is missing required "sub" claim');
|
|
48
65
|
}
|
|
49
66
|
|
|
50
67
|
return {
|
|
51
68
|
userId: payload.sub, // Google User ID
|
|
52
|
-
email: payload.email as string || undefined, // Email might be missing
|
|
69
|
+
email: payload.email as string || undefined, // Email might be missing
|
|
53
70
|
};
|
|
54
71
|
} else {
|
|
72
|
+
console.log('🔹 Regular JWT Token Detected');
|
|
73
|
+
|
|
55
74
|
// 🔹 Regular User Token → Verify with JWT_SECRET
|
|
56
75
|
const secret = new TextEncoder().encode(jwtSecret);
|
|
57
76
|
const { payload } = await jwtVerify(token, secret, {
|
|
@@ -59,47 +78,20 @@ export const verifyToken = async (
|
|
|
59
78
|
issuer: c.env.ISSUER,
|
|
60
79
|
});
|
|
61
80
|
|
|
81
|
+
console.log('✅ Regular JWT Verified! Payload:', payload);
|
|
82
|
+
|
|
62
83
|
if (!payload.userId) {
|
|
63
|
-
throw new Error('JWT is missing required claims (userId)');
|
|
84
|
+
throw new Error('❌ JWT is missing required claims (userId)');
|
|
64
85
|
}
|
|
65
86
|
|
|
66
87
|
if (payload.exp && payload.exp * 1000 < Date.now()) {
|
|
67
|
-
throw new Error('Token has expired');
|
|
88
|
+
throw new Error('❌ Token has expired');
|
|
68
89
|
}
|
|
69
90
|
|
|
70
91
|
return payload as { userId: string; email?: string; roles?: string[] };
|
|
71
92
|
}
|
|
72
|
-
} catch (err) {
|
|
93
|
+
} catch (err: any) {
|
|
94
|
+
console.error('❌ Token Verification Failed:', err.message);
|
|
73
95
|
throw new Error('Invalid or expired token');
|
|
74
96
|
}
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
export const providers = (c: AuthCtx) => ({
|
|
78
|
-
google: {
|
|
79
|
-
serverUrl: 'https://accounts.google.com',
|
|
80
|
-
clientId: c.env.GOOGLE_OAUTH_CLIENT_ID,
|
|
81
|
-
clientSecret: c.env.GOOGLE_OAUTH_CLIENT_SECRET,
|
|
82
|
-
resourceUrl: 'https://www.googleapis.com/oauth2/v2/userinfo',
|
|
83
|
-
},
|
|
84
|
-
facebook: {
|
|
85
|
-
serverUrl: 'https://www.facebook.com/v11.0/dialog/oauth',
|
|
86
|
-
clientId: c.env.FACEBOOK_OAUTH_CLIENT_ID,
|
|
87
|
-
clientSecret: c.env.FACEBOOK_OAUTH_CLIENT_SECRET,
|
|
88
|
-
resourceUrl: 'https://graph.facebook.com/me?fields=id,name,email,picture',
|
|
89
|
-
},
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
export const GENDER_CODE_MAP: Record<string, Gender> =
|
|
93
|
-
VALID_GENDERS_ARRAY.reduce((map, gender) => {
|
|
94
|
-
const key = gender[0];
|
|
95
|
-
map[key] = gender;
|
|
96
|
-
return map;
|
|
97
|
-
}, {} as Record<string, Gender>);
|
|
98
|
-
|
|
99
|
-
export function createEmptyGenderPrompts(): Record<Gender, string> {
|
|
100
|
-
const emptyPrompts: Record<Gender, string> = {} as Record<Gender, string>;
|
|
101
|
-
Object.values(GENDER_CODE_MAP).forEach((gender) => {
|
|
102
|
-
emptyPrompts[gender] = '';
|
|
103
|
-
});
|
|
104
|
-
return emptyPrompts;
|
|
105
|
-
}
|
|
97
|
+
};
|