mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
chore: add custom-jwt-validation example (#40438)
This commit is contained in:
1 parent
9b784791bb
commit
27f8143b66
4 files changed
+155
No files matched your search
@@ -0,0 +1,60 @@
|
||||
// Clerk as a third-party provider alongside Supabase Auth.
|
||||
// Use this template to validate tokens issued by Clerk integration
|
||||
import * as jose from "https://deno.land/x/jose@v4.14.4/index.ts";
|
||||
|
||||
// Obtain from https://clerk.com/setup/supabase
|
||||
// Must supply this value from function env
|
||||
const AUTH_THIRD_PARTY_CLERK_DOMAIN = Deno.env.get(
|
||||
"AUTH_THIRD_PARTY_CLERK_DOMAIN",
|
||||
);
|
||||
|
||||
export 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;
|
||||
}
|
||||
|
||||
async function verifyJWT(jwt: string): Promise<boolean> {
|
||||
try {
|
||||
const JWK = jose.createRemoteJWKSet(
|
||||
new URL(AUTH_THIRD_PARTY_CLERK_DOMAIN ?? ""),
|
||||
);
|
||||
await jose.jwtVerify(jwt, JWK, {
|
||||
algorithms: ["RS256"],
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Validates authorization header
|
||||
export async function AuthMiddleware(
|
||||
req: Request,
|
||||
next: (req: Request) => Promise<Response>,
|
||||
) {
|
||||
if (req.method === "OPTIONS") return await next(req);
|
||||
|
||||
try {
|
||||
const token = getAuthToken(req);
|
||||
const isValidJWT = await verifyJWT(token);
|
||||
|
||||
if (isValidJWT) return await next(req);
|
||||
|
||||
return Response.json({ msg: "Invalid JWT" }, {
|
||||
status: 401,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return Response.json({ msg: e?.toString() }, {
|
||||
status: 401,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Default supabase JWT verification
|
||||
// Use this template to validate tokens issued by Supabase default auth
|
||||
|
||||
import * as jose from "https://deno.land/x/jose@v4.14.4/index.ts";
|
||||
|
||||
// Automatically supplied by Supabase
|
||||
const JWT_SECRET = Deno.env.get("JWT_SECRET");
|
||||
|
||||
export 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;
|
||||
}
|
||||
|
||||
async function verifyJWT(jwt: string): Promise<boolean> {
|
||||
const encoder = new TextEncoder();
|
||||
const secretKey = encoder.encode(JWT_SECRET);
|
||||
try {
|
||||
await jose.jwtVerify(jwt, secretKey);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Validates authorization header
|
||||
export async function AuthMiddleware(
|
||||
req: Request,
|
||||
next: (req: Request) => Promise<Response>,
|
||||
) {
|
||||
if (req.method === "OPTIONS") return await next(req);
|
||||
|
||||
try {
|
||||
const token = getAuthToken(req);
|
||||
const isValidJWT = await verifyJWT(token);
|
||||
|
||||
if (isValidJWT) return await next(req);
|
||||
|
||||
return Response.json({ msg: "Invalid JWT" }, {
|
||||
status: 401,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return Response.json({ msg: e?.toString() }, {
|
||||
status: 401,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# custom-jwt-validation
|
||||
|
||||
This function exemplifies how to use a custom JWT validation.
|
||||
|
||||
Since Supabase legacy JWT Secret will be deprecated, users that would like to verify JWT or integrate with a custom provider should implement it manually.
|
||||
|
||||
> see [Upcoming changes to Supabase API Keys #29260](https://github.com/orgs/supabase/discussions/29260)
|
||||
|
||||
To simplify this task, Supabase provides a collection of JWT validation examples
|
||||
that can be found at [`_shared/jwt/`](https://github.com/supabase/supabase/blob/main/examples/edge-functions/supabase/functions/_shared/jwt) folder.
|
||||
|
||||
## Setup
|
||||
|
||||
1. Copy/download the JWT template, then import and use it inside your edge function.
|
||||
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/supabase/supabase/refs/heads/main/examples/edge-functions/supabase/functions/_shared/jwt/<template>.ts
|
||||
```
|
||||
|
||||
2. Add any required Environment-Variable to a `.env` file, see inside of the
|
||||
respective `_shared/jwt/template.ts` file to find which variables is required.
|
||||
@@ -0,0 +1,19 @@
|
||||
// Using 'default' Supabase auth middleware
|
||||
// Change to a specific provider by importing like that:
|
||||
// import { AuthMiddleware } from "../_shared/jwt/clerk.ts";
|
||||
import { AuthMiddleware } from "../_shared/jwt/default.ts";
|
||||
|
||||
interface reqPayload {
|
||||
name: string;
|
||||
}
|
||||
|
||||
Deno.serve((r) =>
|
||||
AuthMiddleware(r, async (req) => {
|
||||
const { name }: reqPayload = await req.json();
|
||||
const data = {
|
||||
message: `Hello ${name} from foo!`,
|
||||
};
|
||||
|
||||
return Response.json(data);
|
||||
})
|
||||
);
|
||||
Reference in new issue
Block a user