Verify tokens
Your application receives an access token. You verify it before you trust it. You have two ways.
Verify offline with the JWKS
This is the fast path. You fetch the public keys once and cache them. You verify every token locally. Authly never sees the check.
Authly signs tokens with RS256. It publishes the public keys here.
https://api.authly.example/.well-known/jwks.json
Check four things on every token.
- The signature matches a published key.
- The
issclaim equals the Authly issuer. - The
audclaim equals yourclient_id. - The
expclaim is in the future.
Node
import { createRemoteJWKSet, jwtVerify } from "jose";
const jwks = createRemoteJWKSet(
new URL("https://api.authly.example/.well-known/jwks.json"),
);
export async function verify(token) {
const { payload } = await jwtVerify(token, jwks, {
issuer: "https://api.authly.example",
audience: "your_client_id",
});
return payload.sub;
}
Ruby
require "jwt"
require "net/http"
jwks = JSON.parse(Net::HTTP.get(URI("https://api.authly.example/.well-known/jwks.json")))
jwk_loader = ->(options) { JWT::JWK::Set.new(jwks) }
payload, = JWT.decode(token, nil, true, {
algorithms: ["RS256"],
iss: "https://api.authly.example",
verify_iss: true,
aud: "your_client_id",
verify_aud: true,
jwks: jwk_loader,
})
PHP
use Firebase\JWT\JWT;
use Firebase\JWT\JWK;
$jwks = json_decode(file_get_contents(
"https://api.authly.example/.well-known/jwks.json"
), true);
$payload = JWT::decode($token, JWK::parseKeySet($jwks));
Python
import jwt
from jwt import PyJWKClient
jwks = PyJWKClient("https://api.authly.example/.well-known/jwks.json")
signing_key = jwks.get_signing_key_from_jwt(token)
payload = jwt.decode(
token,
signing_key.key,
algorithms=["RS256"],
issuer="https://api.authly.example",
audience="your_client_id",
)
Verify with introspection
Sometimes you want Authly to answer. Introspection tells you if a token is live right now. It also reflects a revoked session, which an offline check cannot see until the token expires.
curl -X POST https://api.authly.example/api/v1/tokens/introspect \
-H "X-Api-Key: YOUR_API_KEY" \
-d token=ACCESS_TOKEN
{
"active": true,
"sub": "1042",
"aud": "your_client_id",
"exp": 1789999999,
"email": "alice@example.com"
}
An invalid or expired token returns { "active": false }. Authly reveals nothing else, so an attacker learns nothing from the response.
Which one to use
Verify offline for most requests. It is fast and needs no round trip. Add an introspection call for high value actions where instant revocation matters, such as a password change or a large payment.