JWKS URL is a mandatory dashboard account field β peer-tier with Partner ID, Issuer DID, and Verifier DID. AIR Kit fetches your JWKS over HTTPS to validate every Partner JWT you sign, so no credential SDK call can succeed until JWKS is live, registered, and matches your signing key.Documentation Index
Fetch the complete documentation index at: https://docs.moca.network/llms.txt
Use this file to discover all available pages before exploring further.
When this is required
| Operation | Where it runs | JWKS required? |
|---|---|---|
airService.issueCredential | Client SDK | Yes |
airService.verifyCredential | Client SDK | Yes |
| Issue on Behalf (REST) | Server-to-server | Yes |
airService.login (account only) | Client SDK | Only when you use bring your own auth |
What AIR does with your JWKS
If AIR cannot fetch your JWKS, or thekid in your JWT header does not appear in keys[], you get a 401 and the credential flow halts.
Three-part checklist
You must complete all three. Each one alone is not enough.Implement the JWKS route
Host a public HTTPS endpoint that returns a JWKS JSON document containing your Partner JWT public key. The canonical Next.js path used across
air-examples is GET /api/.well-known/jwks.Register the full URL in the dashboard
In the Developer Dashboard go to Account β General Settings β JWKS URL and paste the full HTTPS URL that your app actually serves (for example
https://issuer.example.com/api/.well-known/jwks).Implement the route (Next.js)
This is the exact route shipped in every issuer and verifier app inair-examples. It reads your public key from an environment variable, converts PEM β JWK using jose, and sets kid to your Partner ID.
app/api/.well-known/jwks/route.ts
PARTNER_PRIVATE_KEY):
| Variable | Used for |
|---|---|
PARTNER_PUBLIC_KEY | The base64 body of your RS256 or ES256 public key (between the BEGIN/END markers). |
PARTNER_PRIVATE_KEY | The matching private key used to sign your Partner JWT. Server-only. |
SIGNING_ALGORITHM | RS256 or ES256. Must match the key type. |
NEXT_PUBLIC_PARTNER_ID | Your Partner ID. Used as kid so the JWKS key matches the JWT header. |
Register the URL in the Developer Dashboard
- Open the Developer Dashboard and connect your EOA wallet.
- Navigate to Account β General Settings.
- Paste the full URL into the JWKS URL field. Examples:
https://issuer.example.com/api/.well-known/jwks(air-examples path)https://issuer.example.com/jwks.json(plug-and-play template path)
- Save the settings.
Register the exact URL your app actually serves. AIR fetches this exact URL β there is no path discovery or fallback.
Local development (HTTPS tunnel)
AIR servers cannot reachhttp://localhost:3000. You must expose your local dev server over public HTTPS before issue/verify will work.
- ngrok
- cloudflared
https://abc123.ngrok.app/api/.well-known/jwks in the dashboard.curl check:
keys array with a matching kid, fix this before touching the SDK.
The kid rule
The kid (Key ID) glues the JWT to the JWKS. It must match in two places.
| Location | Value | Source |
|---|---|---|
JWT header kid | partnerId | The header you set when signing the Partner JWT in your backend. |
JWKS keys[].kid | partnerId | Returned by your /api/.well-known/jwks route. |
keys[].
Path matrix (do not blindly copy)
Two MocaNetwork-published references ship JWKS at different paths. There is no single canonical URL β you must register the one your deployment actually serves.| Source | Path served | Where it comes from |
|---|---|---|
air-examples (Next.js apps) | /api/.well-known/jwks | src/app/api/.well-known/jwks/route.ts |
| Plug-and-play issuer template | /jwks.json | Generated at build time, served as a static asset |
One Partner ID = one registered JWKS URL
Each Partner ID has a single JWKS URL slot in the dashboard. When your issuer and verifier apps share a Partner ID β which is the standard layout β you only need one JWKS endpoint registered.- Register the issuerβs JWKS URL (it is the side that always needs public hosting first).
- The verifier signs its own Partner JWTs locally using the same
partnerIdand akidthat appears in the issuerβs published JWKS. AIR fetches the registered URL regardless of which app produced the JWT. - If issuer and verifier are deployed at different hosts but share a Partner ID, make sure both sign with a
kidthat the registered JWKS exposes.
Troubleshooting
When something fails after this checklist looks done, jump to the matching block in Common errors:- JWKS endpoint unreachable β AIR cannot fetch your URL.
- Invalid signature β JWKS reachable but signature does not validate.
- kid not found β JWT header
kidis not present inkeys[].
Related
- Partner Authentication (Partner JWT) β how to sign the JWTs that this JWKS validates.
- Setting Up Your Partner Account β the four mandatory account fields, including JWKS URL.
- AIR Kit Developer Dashboard β where the JWKS URL field lives in the dashboard UI.