From 671fb74b944fa501a830e76b1de98d28b3973b00 Mon Sep 17 00:00:00 2001 From: Ardis Lu Date: Fri, 25 Mar 2022 00:06:32 -0700 Subject: [PATCH] Deploy Function for Google auth proxy Need to update env variables on the web UI before updating the frontend --- functions/api.js | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 functions/api.js diff --git a/functions/api.js b/functions/api.js new file mode 100644 index 0000000..39271c1 --- /dev/null +++ b/functions/api.js @@ -0,0 +1,80 @@ +function base64UrlEncode(s) { + return btoa(s) + .replaceAll('=', '') + .replaceAll('+', '-') + .replaceAll('/', '_'); +} + +async function sign(message, privateKey) { + const cleanedKey = privateKey + .replace('-----BEGIN PRIVATE KEY-----', '') + .replace('-----END PRIVATE KEY-----', '') + .replaceAll(/\r\n|\n|\r/g, ''); + const keyBuffer = Uint8Array.from(atob(cleanedKey), c => c.charCodeAt(0)); + + const signingKey = await crypto.subtle.importKey( + 'pkcs8', + keyBuffer, + { + name: 'RSASSA-PKCS1-V1_5', + hash: 'SHA-256' + }, + false, + ['sign'] + ); + + const signatureBuffer = await crypto.subtle.sign('RSASSA-PKCS1-V1_5', signingKey, message); + return base64UrlEncode(String.fromCharCode(...new Uint8Array(signatureBuffer))); +} + +async function getGoogleAuthToken(clientEmail, privateKey, scopes) { + const header = base64UrlEncode(JSON.stringify({ + alg: 'RS256', + typ: 'JWT' + })); + + const now = Math.round(Date.now() / 1000); + const expires = now + 3600; + const payload = base64UrlEncode(JSON.stringify({ + iss: clientEmail, + aud: 'https://oauth2.googleapis.com/token', + exp: expires, + iat: now, + scope: scopes + })); + + const unsignedJwt = `${header}.${payload}`; + const signature = await sign(unsignedJwt, privateKey); + const jwt = `${unsignedJwt}.${signature}`; + + const response = await fetch('https://oauth2.googleapis.com/token', { + method: 'POST', + body: JSON.stringify({ + assertion: jwt, + grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer' + }) + }); + const oauth = await response.json(); + + return oauth.access_token; +} + +export async function onRequestGet({ request, env }) { + const url = new URL(request.url); + const queryString = decodeURIComponent(url.search.substring(1)); + + // Cloudflare Workers inserts "//" in front of all environment variables, need to delete it + const email = env.EMAIL.substring(2) // E.g. "example@example.com" + const privateKey = env.PRIVATE_KEY.substring(2) // E.g. "-----BEGIN PRIVATE KEY-----\n...EXAMPLE...\n-----END PRIVATE KEY-----\n" + const scopes = env.SCOPES.substring(2) // E.g. "https://example.com/auth/scope1 https://example.com/auth/scope2" + + const token = await getGoogleAuthToken(email, privateKey, scopes); + + const response = await fetch(queryString, { + headers: { + Authorization: `Bearer ${token}` + } + }); + + return response; +} -- 2.47.3