Avnology ID
Guides

Verify JWTs (any language)

Raw HTTP + any JOSE library. Useful for Ruby, PHP, .NET, Rust, or any stack without a first-party Avnology SDK.

Verify JWTs (any language)

Not on TypeScript / Go / Python? The JWKS endpoint is standard OIDC. Any mainstream JOSE library can verify tokens against it. Below is the recipe.

Step 1: Fetch and cache the JWKS

GET https://api-id.avnology.net/.well-known/jwks.json

{
  "keys": [
    {
      "kid": "2026-04-15",
      "kty": "RSA",
      "alg": "RS256",
      "use": "sig",
      "n":   "…",
      "e":   "AQAB"


Rules:

  • Cache for up to 5 minutes.
  • Respect Cache-Control: max-age.
  • On a verify failure with kid not in the cached set, refetch once (rate-limit refetches to once per 30 seconds to prevent JWKS DoS).

Step 2: Verify the token

Decode the JWT header, find the matching kid in the JWKS, verify the signature. Enforce:

ClaimRule
algHeader must be RS256, RS384, RS512, ES256, ES384, or ES512. Reject none and HS256.
issMust equal the issuer you expect (e.g. https://api-id.avnology.net)
audMust contain your configured audience (if set)
expMust be in the future, allowing 30s skew
nbfIf present, must be in the past, allowing 30s skew
iatInformational. Don't use for freshness checks.

Reject the token if any check fails.

Step 3: Extract claims

Avnology JWTs carry these payload fields (no Ory terminology):

ClaimTypeDescription
substringIdentity ID, usr_…
user_idstringAlias of sub
organization_idstringorg_… if scoped
session_idstringses_…
scopespace-separated stringOAuth scopes
permissionsstring[]Resolved Keto permissions
aalstringAssurance level (aal1, aal2, aal3)
issstringIssuer base URL
audstringstring[]
iat, exp, nbfintUnix seconds

Language-specific recipes

Ruby (jwt gem)

require "jwt"
require "net/http"
require "json"

JWKS_URI   = URI("https://api-id.avnology.net/.well-known/jwks.json")
EXPECTED_ISSUER   = "https://api-id.avnology.net"
EXPECTED_AUDIENCE = "my-api"

def jwks
  @jwks ||= JSON.parse(Net::HTTP.get(JWKS_URI















PHP (firebase/php-jwt)

use Firebase\JWT\JWT;
use Firebase\JWT\JWK;

$jwks = json_decode(
    file_get_contents("https://api-id.avnology.net/.well-known/jwks.json"),
    true,
);
$keys = JWK::parseKeySet($jwks);
$claims =




.NET (Microsoft.IdentityModel.Tokens)

using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.















Rust (jsonwebtoken)

Common pitfalls

  • Don't verify with HS256. Avnology only issues asymmetrically-signed tokens. Reject the header's alg if it's HS256 or none.
  • Don't skip exp verification "just during testing." Every JOSE library has a sandbox mode that omits exp; it's a footgun in production.
  • Cache the JWKS. Re-fetching per request will melt your gateway and get you rate-limited.
  • Handle key rotation. On kid miss, refetch once. Don't hard-fail.