Overview
How tokens are signed, how your API verifies them without asking us, and what the client is protecting.
Two things decide whether a request is authentic: the key that signed the access token, and the key your API checks it against. Both are yours, and the second one never has to be a secret you keep.
Access tokens are signed, not shared
Every access token an environment issues is a JWT signed with an asymmetric key pair. Your environment holds the private half; the public half is published, and that is all anyone needs to verify a token.
There is no shared signing secret to copy into your backend, no secret to rotate across services, and nothing that turns into a breach when one service leaks its configuration.
The format follows RFC 7519 for the token itself and RFC 9068 for its use as an OAuth 2.0 access token, so any standard JWT library verifies it.
Verifying in your own API
Fetch the public keys from the environment's JWKS endpoint and verify the signature. The set is JWK format, as served by every OpenID provider:
https://<environment>.nulvless.co/auth/.well-known/jwks.jsonimport { createRemoteJWKSet, jwtVerify } from 'jose';
const keys = createRemoteJWKSet(
new URL('https://<environment>.nulvless.co/auth/.well-known/jwks.json'),
);
const { payload } = await jwtVerify(token, keys);The token's header carries a kid naming which key signed it, so a library
picks the right one out of the set on its own. Cache the set — your library
almost certainly does — and let it refetch when it meets a kid it does not
know.
Verifying a signature tells you the token is genuine and unexpired. It does not
tell you the user still has the permissions inside it, because a claim is a
snapshot from when the token was minted. When the question is "may they do
this", call verify instead of reading the JWT.
Refresh tokens
A refresh token is bound to one session, and using it rotates it: the response carries the next one, and the one you sent stops working. A refresh token that turns up again after that is treated as a leak and the session is ended.
There is one exception, and it exists because networks are unreliable. A repeat of the token you just used is tolerated for a short window and answered with a fresh pair, so a request that was retried after a timeout does not sign the user out. The browser SDK handles this for you — it shares one refresh between concurrent callers and across tabs, so this case should not arise from your own code.
This is the rotation-and-reuse-detection behaviour recommended for public clients in RFC 9700, the OAuth 2.0 security best practice.
Do not store a refresh token anywhere a page can read it back later and replay it out of order — a second copy in your own state is the usual way a session gets ended for a leak that never happened. Let the SDK own it.