Files
continuum-common/packages/ts-core/src/auth.ts
T
octoturge 0fa4bfaf45 Simplify ts-core auth.ts; fix bun-types resolution in monorepo workspace
auth.ts: dropped the legacy HS256-shared-secret verification path, keeping
only the JWKS path Supabase recommends now — one code path instead of two.

Also fixes a real bug: @types/bun's ambient types didn't resolve inside a
bun workspace (its internal 'bun-types' reference can't hoist into a nested
package's node_modules the same way it does in a flat install). Depending on
bun-types directly instead of @types/bun fixes it — verified with a clean
'bun run typecheck'.
2026-08-28 18:28:06 +00:00

43 lines
1.3 KiB
TypeScript

import { createRemoteJWKSet, jwtVerify, type JWTPayload } from "jose";
export interface SupabaseClaims extends JWTPayload {
sub: string;
email?: string;
role?: string;
}
export class JwtVerificationError extends Error {
constructor(message: string, readonly cause?: unknown) {
super(message);
this.name = "JwtVerificationError";
}
}
/**
* Verifies a Supabase-issued access token against the project's public
* JWKS (fetched once and cached). `supabaseUrl` is your project URL, e.g.
* `https://xyzcompany.supabase.co`.
*/
export function createSupabaseJwtVerifier(supabaseUrl: string) {
const jwks = createRemoteJWKSet(new URL("/auth/v1/.well-known/jwks.json", supabaseUrl));
return {
async verify(token: string): Promise<SupabaseClaims> {
try {
const { payload } = await jwtVerify(token, jwks, { audience: "authenticated" });
return payload as SupabaseClaims;
} catch (err) {
throw new JwtVerificationError("failed to verify Supabase JWT", err);
}
},
};
}
export function extractBearerToken(authorizationHeader: string | null | undefined): string {
const [scheme, token] = (authorizationHeader ?? "").split(" ");
if (scheme !== "Bearer" || !token) {
throw new JwtVerificationError("Authorization header is not a Bearer token");
}
return token;
}