snapshot of https://github.com/marmelab/atomic-crm.git (main, 2026-09-18; blobs > 131072B omitted)
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
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
This commit is contained in:
80
supabase/functions/_shared/authentication.ts
Normal file
80
supabase/functions/_shared/authentication.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
// 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");
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user