From d30c6e06d5a82d28defbcc6534a8e68d03c2cd84 Mon Sep 17 00:00:00 2001 From: regalijan Date: Fri, 20 Oct 2023 11:18:03 -0400 Subject: [PATCH] Add auto jwt refreshing --- functions/_middleware.ts | 68 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/functions/_middleware.ts b/functions/_middleware.ts index 75042fa..b8ed629 100644 --- a/functions/_middleware.ts +++ b/functions/_middleware.ts @@ -98,6 +98,74 @@ async function refreshAuth(context: RequestContext) { delete context.data.sid; + const jwtPayload = context.request.headers + .get("authorization") + ?.replace("Bearer ", "") + .split(".") + .at(1); + + if (jwtPayload) { + let jwtData: { [k: string]: any }; + + try { + jwtData = JSON.parse( + atob(jwtPayload.replaceAll("-", "+").replaceAll("_", "/")), + ); + } catch { + return jsonError("JWT is malformed", 400); + } + + jwtData.email = userData.email; + jwtData.exp = Math.floor(Date.now() / 1000) + userData.expires_in; + jwtData.iat = Math.floor(Date.now() / 1000); + jwtData.name = userData.username; + jwtData.permissions = userData.permissions; + jwtData.picture = + userData.avatar ?? "https://carcrushers.cc/files/logo192.png"; + + const key = await crypto.subtle.importKey( + "raw", + // @ts-expect-error + Uint8Array.from( + atob( + context.env.JWT_SIGNING_KEY.replaceAll("-", "+").replaceAll("_", "/"), + ), + (m) => m.codePointAt(0), + ), + { hash: "SHA-256", name: "HMAC" }, + false, + ["sign"], + ); + + const jwtBase = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.${btoa( + JSON.stringify(jwtData), + ) + .replaceAll("+", "-") + .replaceAll("/", "_") + .replaceAll("=", "")}`; + + const signature = btoa( + String.fromCodePoint( + ...new Uint8Array( + await crypto.subtle.sign( + "HMAC", + key, + new TextEncoder().encode(jwtBase), + ), + ), + ), + ) + .replaceAll("+", "-") + .replace("/", "_") + .replaceAll("=", ""); + + const response = await context.next(); + + response.headers.set("refreshed-token", `${jwtBase}.${signature}`); + + return response; + } + return await context.next(); }