Skip to content

Commit 39176e3

Browse files
committed
feat: adding hybrid jwt verification
Allows verify new JWTs as well legacy
1 parent b4918f3 commit 39176e3

1 file changed

Lines changed: 26 additions & 5 deletions

File tree

  • internal/functions/serve/templates

internal/functions/serve/templates/main.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { STATUS_CODE, STATUS_TEXT } from "https://deno.land/std/http/status.ts";
22
import * as posix from "https://deno.land/std/path/posix/mod.ts";
33

4-
import * as jose from "https://deno.land/x/jose@v4.13.1/index.ts";
4+
import * as jose from "jsr:@panva/jose@6";
55

66
const SB_SPECIFIC_ERROR_CODE = {
77
BootError:
@@ -29,8 +29,9 @@ const SB_SPECIFIC_ERROR_REASON = {
2929
// OS stuff - we don't want to expose these to the functions.
3030
const EXCLUDED_ENVS = ["HOME", "HOSTNAME", "PATH", "PWD"];
3131

32-
const JWT_SECRET = Deno.env.get("SUPABASE_INTERNAL_JWT_SECRET")!;
3332
const HOST_PORT = Deno.env.get("SUPABASE_INTERNAL_HOST_PORT")!;
33+
const JWT_SECRET = Deno.env.get("SUPABASE_INTERNAL_JWT_SECRET")!;
34+
const JWKS_ENDPOINT = Deno.env.get("SUPABASE_URL")! + "/auth/v1/.well-known/jwks.json";
3435
const DEBUG = Deno.env.get("SUPABASE_INTERNAL_DEBUG") === "true";
3536
const FUNCTIONS_CONFIG_STRING = Deno.env.get(
3637
"SUPABASE_INTERNAL_FUNCTIONS_CONFIG",
@@ -105,13 +106,28 @@ function getAuthToken(req: Request) {
105106
return token;
106107
}
107108

108-
async function verifyJWT(jwt: string): Promise<boolean> {
109+
async function verifyLegacyJWT(jwt: string): Promise<boolean> {
109110
const encoder = new TextEncoder();
110111
const secretKey = encoder.encode(JWT_SECRET);
111112
try {
112113
await jose.jwtVerify(jwt, secretKey);
113114
} catch (e) {
114-
console.error(e);
115+
console.error('Symmetric Legacy JWT verification error', e);
116+
return false;
117+
}
118+
return true;
119+
}
120+
121+
// Lazy-loading JWKs
122+
let jwks = null;
123+
async function verifyJWT(jwt: string): Promise<boolean> {
124+
try {
125+
if (!jwks) {
126+
jwks = jose.createRemoteJWKSet(new URL(JWKS_ENDPOINT));
127+
}
128+
await jose.jwtVerify(jwt, jwks);
129+
} catch (e) {
130+
console.error('Asymmetric JWT verification error', e);
115131
return false;
116132
}
117133
return true;
@@ -162,7 +178,12 @@ Deno.serve({
162178
const isValidJWT = await verifyJWT(token);
163179

164180
if (!isValidJWT) {
165-
return getResponse({ msg: "Invalid JWT" }, STATUS_CODE.Unauthorized);
181+
console.log('Asymmetric JWT verification failed; attempting legacy verification.')
182+
const isValidLegacyJWT = await verifyLegacyJWT(token);
183+
184+
if (!isValidLegacyJWT) {
185+
return getResponse({ msg: "Invalid JWT" }, STATUS_CODE.Unauthorized);
186+
}
166187
}
167188
} catch (e) {
168189
console.error(e);

0 commit comments

Comments
 (0)