Skip to content

JWT Verification

from authfort_service import ServiceAuth, TokenPayload, TokenVerificationError

service = ServiceAuth(
    jwks_url="https://auth.example.com/.well-known/jwks.json",
    issuer="authfort",
)

try:
    payload: TokenPayload = await service.verify_token(token)
    print(payload.sub)    # user ID
    print(payload.email)  # user email
    print(payload.roles)  # ["admin", "editor"]
except TokenVerificationError as e:
    print(e.message)  # "Token expired"
    print(e.code)     # "token_expired"
from authfort_service import ServiceAuth, TokenPayload, TokenVerificationError

service = ServiceAuth(
    jwks_url="https://auth.example.com/.well-known/jwks.json",
    issuer="authfort",
)

try:
    payload: TokenPayload = await service.verify_token(token)
    print(payload.sub)    # user ID
    print(payload.email)  # user email
    print(payload.roles)  # ["admin", "editor"]
except TokenVerificationError as e:
    print(e.message)  # "Token expired"
    print(e.code)     # "token_expired"

The verified token contains these fields:

FieldTypeDescription
substrUser ID
emailstrUser email
namestr | NoneUser display name
roleslist[str]User roles
token_versionintToken version (for revocation checks)
expintExpiration timestamp
iatintIssued-at timestamp
issstrIssuer

The service fetches public keys from the JWKS endpoint and caches them:

  1. First request — fetches keys from JWKS, caches them
  2. Subsequent requests — uses cached keys (no network call)
  3. Cache expires (jwks_cache_ttl) — next request refreshes the cache
  4. Unknown key ID — triggers an immediate refresh (handles key rotation)

This means verification has zero network latency after the initial fetch, except during key rotation or cache expiry.

To prevent hammering the JWKS endpoint (e.g., during an attack with invalid tokens), the fetcher rate-limits itself. If a fetch was attempted recently, subsequent unknown-key requests fail fast rather than making another network call.

CodeMeaning
token_expiredToken’s exp claim is in the past
invalid_tokenSignature invalid, malformed, or missing claims
invalid_issuerToken’s iss doesn’t match expected issuer
key_not_foundNo matching public key in JWKS