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)