Examples
Here are a few example authorizers to get you started. Most applications will use a variation on one of these methods.
Example: JWT Verification using JWKs
In this case, the legacy authentication method uses JWTs. The public key to verify the JWTs can be retrieved from a public JWKS endpoint. This code includes two secrets: PASSAGE_API_KEY and PUBLIC_JWKS. The Passage API Key is required for the context.getOrCreateUser()
function to work.
import * as jose from "https://deno.land/x/[email protected]/index.ts";
export default async (event: PassageEvent, context: AuthorizerContext) => {
const token = context.getAuthHeaderToken();
if (!token) throw new Error("Missing Authorization header");
const PUBLIC_JWKS = event.secrets.PUBLIC_JWKS;
if (!PUBLIC_JWKS) throw new Error("Missing PUBLIC_JWKS secret");
try {
const jwks = JSON.parse(PUBLIC_JWKS);
const JWKS = jose.createLocalJWKSet(jwks);
const { payload } = await jose.jwtVerify(token, JWKS);
const email = payload.email as string;
if (email) {
const passageUser = await context.getOrCreateUser(email);
// Here you may want to link your User with a PassageUser
// This can be done by either storing the PassageUser Id in your system
// Or by storing your User ID as metadata on the Passage User
context.allowAccess(passageUser.id);
} else {
context.denyAccess("User not found");
}
} catch (error) {
context.denyAccess(error.message);
}
};
Example: JWT Verification using Public Key
In this case, the legacy authentication method uses JWTs. The public key to verify the JWTs can be stored in a secret. This code includes two secrets: PASSAGE_API_KEY and PUBLIC_KEY. The Passage API Key is required for the context.getOrCreateUser()
function to work.
import * as jose from "https://deno.land/x/[email protected]/index.ts";
export default async (event: PassageEvent, context: AuthorizerContext) => {
const token = context.getAuthHeaderToken();
if (!token) throw new Error("Missing Authorization header");
const PUBLIC_KEY= event.secrets.PUBLIC_KEY;
if (!PUBLIC_KEY) throw new Error("Missing PUBLIC_KEY secret");
try {
const { payload } = await jose.jwtVerify(token, PUBLIC_KEY);
const email = payload.email as string;
if (email) {
const passageUser = await context.getOrCreateUser(email);
// Here you may want to link your User with a PassageUser
// This can be done by either storing the PassageUser Id in your system
// Or by storing your User ID as metadata on the Passage User
context.allowAccess(passageUser.id);
} else {
context.denyAccess("User not found");
}
} catch (error) {
context.denyAccess(error.message);
}
};
Example: JWT Verification using JWT Secret
In this case, the legacy authentication method uses JWTs. The JWT Secret can be stored in a secret. This code includes two secrets: PASSAGE_API_KEY and JWT_SECRET. The Passage API Key is required for the context.getOrCreateUser()
function to work.
import * as jose from "https://deno.land/x/[email protected]/index.ts";
export default async (event: PassageEvent, context: AuthorizerContext) => {
const token = context.getAuthHeaderToken();
if (!token) throw new Error("Missing Authorization header");
const JWT_SECRET = event.secrets.JWT_SECRET;
if (!JWT_SECRET) throw new Error("Missing JWT_SECRET secret");
try {
const secret = new TextEncoder().encode(SUPABASE_JWT_SECRET);
const { payload } = await jose.jwtVerify(token, secret);
const email = payload.email as string;
if (email) {
const passageUser = await context.getOrCreateUser(email);
// Here you may want to link your User with a PassageUser
// This can be done by either storing the PassageUser Id in your system
// Or by storing your User ID as metadata on the Passage User
context.allowAccess(passageUser.id);
} else {
context.denyAccess("User not found");
}
} catch (error) {
context.denyAccess(error.message);
}
};
Example: Stateful Sessions using an API for Verification
In this case, the legacy authentication method uses stateful sessions that are a random string of bytes. Session tokens are stored in the legacy database and verified when requests are made. To authenticate a user, this authorizer makes an API call to an endpoint that returns the current user’s information based on the legacy session token provided. This code only requires one secret: PASSAGE_API_KEY. The Passage API Key is required for the context.getOrCreateUser()
functions to work.
export default async (event: PassageEvent, context: AuthorizerContext) => {
const token = context.getAuthHeaderToken();
if (!token) throw new Error("Missing Authorization header");
try {
const resp = await fetch(
"https://00d3a2884575.ngrok.io/currentuser",
{
headers: {
Cookie: "session=" + token
}
}
)
if (resp.redirected) { // or your app may return a different status code
context.denyAccess("invalid response")
return
}
const data = await resp.json()
const passageUser = await context.getOrCreateUser(data.email)
// Here you may want to link your User with a PassageUser
// This can be done by either storing the PassageUser Id in your system
// Or by storing your User ID as metadata on the Passage User
context.allowAccess(passageUser.id)
} catch (err) {
context.denyAccess(err.message)
}
}
Last updated