From bc8bc1159dea36648c02b516bb17bf482766bc4c Mon Sep 17 00:00:00 2001 From: dwindown Date: Tue, 23 Dec 2025 11:25:20 +0700 Subject: [PATCH] Fix JWT generation using native Deno Web Crypto API - Remove external jose library dependency that was causing import errors - Use native crypto.subtle API available in Deno - Manual base64url encoding for JWT header, payload, and signature - Use RSASSA-PKCS1-v1_5 with SHA-256 for RS256 algorithm - Remove cat heredoc wrapper from file --- .../create-google-meet-event/index.ts | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/supabase/functions/create-google-meet-event/index.ts b/supabase/functions/create-google-meet-event/index.ts index b6e0a5d..4c77391 100644 --- a/supabase/functions/create-google-meet-event/index.ts +++ b/supabase/functions/create-google-meet-event/index.ts @@ -27,30 +27,11 @@ interface CreateMeetRequest { notes?: string; } -// Function to create JWT and get access token +// Function to create JWT and get access token using native Web Crypto API async function getGoogleAccessToken(serviceAccount: GoogleServiceAccount): Promise { try { - // Use a different JWT library that's more compatible with Google's requirements - const { importKey, sign } = await import("https://deno.land/x/jose@v4.15.1/node/crypto.ts"); - const now = Math.floor(Date.now() / 1000); - // Convert PEM format private key to CryptoKey - const privateKey = await importKey( - "pkcs8", - // Convert PEM to binary - Uint8Array.from( - atob(serviceAccount.private_key - .replace(/-----BEGIN PRIVATE KEY-----/g, "") - .replace(/-----END PRIVATE KEY-----/g, "") - .replace(/\s/g, "")), - c => c.charCodeAt(0) - ), - { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, - false, - ["sign"] - ); - // Build JWT header and payload manually const header = { alg: "RS256", @@ -65,21 +46,40 @@ async function getGoogleAccessToken(serviceAccount: GoogleServiceAccount): Promi iat: now, }; - // Encode header and payload - const encodedHeader = btoa(JSON.stringify(header)) - .replace(/\+/g, "-") - .replace(/\//g, "_") - .replace(/=/g, ""); - - const encodedPayload = btoa(JSON.stringify(payload)) - .replace(/\+/g, "-") - .replace(/\//g, "_") - .replace(/=/g, ""); + // Encode header and payload (base64url) + const base64UrlEncode = (str: string) => { + return btoa(str) + .replace(/\+/g, "-") + .replace(/\//g, "_") + .replace(/=/g, ""); + }; + const encodedHeader = base64UrlEncode(JSON.stringify(header)); + const encodedPayload = base64UrlEncode(JSON.stringify(payload)); const signatureInput = `${encodedHeader}.${encodedPayload}`; + // Convert PEM to binary + const keyData = serviceAccount.private_key + .replace(/-----BEGIN PRIVATE KEY-----/g, "") + .replace(/-----END PRIVATE KEY-----/g, "") + .replace(/\s/g, ""); + + const binaryKey = Uint8Array.from(atob(keyData), c => c.charCodeAt(0)); + + // Import private key using native Web Crypto API + const privateKey = await crypto.subtle.importKey( + "pkcs8", + binaryKey, + { + name: "RSASSA-PKCS1-v1_5", + hash: "SHA-256", + }, + false, + ["sign"] + ); + // Sign the JWT - const signature = await sign( + const signature = await crypto.subtle.sign( "RSASSA-PKCS1-v1_5", privateKey, new TextEncoder().encode(signatureInput)