Your app stays where it is hosted today; Volly gates who reaches it. Every
request Volly proxies to your origin carries a short-lived, ES256-signed JWT in
the X-Volly-Jwt header identifying the signed-in viewer. Your origin is
the enforcement point: Volly does not sit between your origin and the open
internet, so a request without a valid token must be rejected by your code.
This directory is the canonical, dependency-free implementation of that check.
Copy verify.mjs into your project (or let your coding agent reproduce it in
your framework — see SKILL.md).
Reject the request unless ALL of these hold:
| Check | What skipping it means |
|---|---|
A token is present in X-Volly-Jwt |
anyone on the internet reaches your app |
| Its signature verifies against Volly's published JWKS | anyone can forge a viewer token |
aud equals your app's canonical URL |
a token minted for another gated app grants access here |
| It is not expired | a leaked token works forever |
Volly's activation gate probes your origin for exactly these four behaviors — your app will not serve traffic through Volly until all of them pass.
- JWKS URL:
https://app.volly.so/.well-known/volly-jwks.json - Issuer (
iss):https://volly.so - Audience (
aud): your app's canonical URL,https://{org}-{app}.volly.so— shown on your project's settings page. Pin it as a constant; never accept any other value. - Token lifetime: ≤ 5 minutes, minted per proxied request. Cache the JWKS (the reference implementation caches for 5 minutes) but never cache a verification result across requests.
After verification the token's payload gives you the viewer's identity:
{
"sub": "viewer@customer.com",
"email": "viewer@customer.com",
"org_id": "…",
"app_id": "…",
"iss": "https://volly.so",
"aud": "https://acme-crm.volly.so",
"iat": 1710000000,
"exp": 1710000300
}Use email for per-user behavior; it is verified by Volly's viewer gate.
import { createVollyVerifier } from "./verify.mjs";
const verifyVollyToken = createVollyVerifier({
audience: "https://acme-crm.volly.so", // YOUR app's URL — pin it
});
// Express-style middleware
app.use(async (req, res, next) => {
const viewer = await verifyVollyToken(req.get("x-volly-jwt"));
if (!viewer) {
return res.status(401).send("Unauthorized");
}
req.viewer = viewer; // { sub, email, org_id, app_id }
next();
});Any framework works the same way: read the X-Volly-Jwt header, call the
verifier, respond 401 when it returns null. Apply it to every route —
including static assets, API routes, and health endpoints you don't want
public. A single unprotected route is an unprotected app.
No telemetry, no phone-home, no dependencies. It fetches Volly's public JWKS and nothing else. Read it — it is one file.