Skip to content

Instantly share code, notes, and snippets.

@joshtwist
Created October 14, 2022 20:24
Show Gist options
  • Save joshtwist/2abc51bacc2b0fd932a32261e1ed4887 to your computer and use it in GitHub Desktop.
Save joshtwist/2abc51bacc2b0fd932a32261e1ed4887 to your computer and use it in GitHub Desktop.
import {
ZuploContext,
ZuploRequest,
OpenIdJwtInboundPolicy,
InboundPolicyHandler,
OpenIdJwtInboundPolicyOptions,
Auth0JwtInboundPolicy,
Auth0JwtInboundPolicyOptions,
} from "@zuplo/runtime";
interface JwtMapEntry {
name: string;
iss: string;
options: any;
handler: any;
}
const BEARER_PREFIX = "bearer ";
// This is a map of issuers to policies
// we're using the same policies available in the
// library but are using them programmatically
// I've done two for you :)
const issuerPolicyMap: JwtMapEntry[] = [
// Customer Vault (Imburse Generated)
{
name: "customer-vault-policy",
iss: "https://ci-vault.imburse.net/",
handler: OpenIdJwtInboundPolicy,
// These are the same options documented here:
// https://zuplo.com/docs/policies/open-id-jwt-auth-inbound
options: {
secret: "anders-gate-is-a-sci-fi-novel",
},
},
// Auth0
{
name: "auth0-policy",
iss: "https://dev-imbursepayments.eu.auth0.com/",
handler: Auth0JwtInboundPolicy,
// these are the same options documented here:
// https://zuplo.com/docs/policies/auth0-jwt-auth-inbound
options: {
auth0Domain: "https://you-fill-this-in",
audience: "https://you-fill-this-in/",
},
},
];
const unauthorizedResponse = (message: string) => {
return new Response(message, { status: 401 });
};
export default async function (request: ZuploRequest, context: ZuploContext) {
// First, we're going to read the authorization header to
// get the JWT token - reject if none found or malformed
const authHeader = request.headers.get("authorization");
if (!authHeader) {
return unauthorizedResponse(`No Authorization header`);
}
if (authHeader.toLowerCase().indexOf(BEARER_PREFIX) !== 0) {
return unauthorizedResponse(
`Invalid bearer token format for Authorization header`
);
}
const jwt = authHeader.substring(BEARER_PREFIX.length);
if (!jwt || jwt.length === 0) {
return unauthorizedResponse(`No JWT token on bearer`);
}
try {
// Next we're going to split and decode it to look at the issuer
const [headerEncoded, dataEncoded, signatureEncoded] = jwt.split(".");
const data = atob(dataEncoded);
const payload = JSON.parse(data);
// find the matching policy in our map
const policy = issuerPolicyMap.find((ipm) => ipm.iss === payload.iss);
if (!policy) {
return unauthorizedResponse(`Issuer '${payload.iss}' not recognized`);
}
// invoke that policy and call the result
return policy.handler(request, context, policy.options, policy.name);
} catch (err) {
context.log.error(err, err.toString());
return unauthorizedResponse("Authentication error");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment