Files
upstream-mirror 93ecc1a6f8
Some checks failed
✅ Check / 🔬 ESLint (push) Failing after 21s
✅ Check / 🏷️ Typecheck (push) Failing after 11s
✅ Check / 🔎 Test (push) Failing after 11s
✅ Check / e2e-test (push) Failing after 11s
✅ Check / 🔨 Build (push) Failing after 11s
🚀 Deploy / 🚀 Deploy (doc) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (demo) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (supabase) (push) Failing after 18s
snapshot of https://github.com/marmelab/atomic-crm.git (main, 2026-09-18; blobs > 131072B omitted)
2026-09-18 01:48:50 +05:00

81 lines
2.4 KiB
TypeScript

// Based on https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/_shared/jwt/default.ts
import * as jose from "jsr:@panva/jose@6";
import { createClient, type User } from "jsr:@supabase/supabase-js@2";
import { createErrorResponse } from "./utils.ts";
const SUPABASE_JWT_ISSUER =
Deno.env.get("SB_JWT_ISSUER") ?? Deno.env.get("SUPABASE_URL") + "/auth/v1";
const SUPABASE_JWT_KEYS = jose.createRemoteJWKSet(
new URL(Deno.env.get("SUPABASE_URL")! + "/auth/v1/.well-known/jwks.json"),
);
function getAuthToken(req: Request) {
const authHeader = req.headers.get("authorization");
if (!authHeader) {
throw new Error("Missing authorization header");
}
const [bearer, token] = authHeader.split(" ");
if (bearer !== "Bearer") {
throw new Error(`Auth header is not 'Bearer {token}'`);
}
return token;
}
function verifySupabaseJWT(jwt: string) {
return jose.jwtVerify(jwt, SUPABASE_JWT_KEYS, {
issuer: SUPABASE_JWT_ISSUER,
});
}
/**
* Validates the Authorization header to ensure that a user is authenticated.
*/
export const AuthMiddleware = async (
req: Request,
next: (req: Request) => Promise<Response>,
) => {
if (req.method === "OPTIONS") return await next(req);
try {
const token = getAuthToken(req);
const isValidJWT = await verifySupabaseJWT(token);
if (isValidJWT) return await next(req);
return createErrorResponse(401, "Invalid authentication");
} catch (e) {
return createErrorResponse(401, e?.toString() || "Unauthorized");
}
};
/**
* Get the authenticated user using the authorization header.
* User will be undefined for OPTIONS requests.
*/
export const UserMiddleware = async (
req: Request,
next: (req: Request, user?: User) => Promise<Response>,
) => {
if (req.method === "OPTIONS") return await next(req);
try {
const authHeader = req.headers.get("Authorization")!;
const localClient = createClient(
Deno.env.get("SUPABASE_URL") ?? "",
Deno.env.get("SB_PUBLISHABLE_KEY") ?? "",
{ global: { headers: { Authorization: authHeader } } },
);
const { data, error: authError } = await localClient.auth.getUser();
if (!data?.user || authError) {
return createErrorResponse(401, "Unauthorized");
}
return next(req, data.user);
} catch (err) {
return createErrorResponse(401, err?.toString() || "Unauthorized");
}
};