AXIAM PHP SDK

JwksVerifier
in package

FinalYes

Local EdDSA/Ed25519 JWKS verification (CONTRACT.md D-08).

Keys are sourced via OIDC discovery (GET /.well-known/openid-configuration -> jwks_uri, falling back to {baseUrl}/oauth2/jwks if discovery is unavailable or omits jwks_uri), TTL-cached, and refetched exactly once when an unknown kid is encountered before failing closed.

Two security invariants (every sibling SDK independently confirmed both):

  • Pitfall 5 / T-alg-confusion: the header alg is pinned to EdDSA BEFORE any key lookup is attempted. A token never gets to choose its own verification algorithm.
  • Pitfall 3 / T-cross-tenant: GET /oauth2/jwks is organization-wide, not tenant-scoped, so a validly-signed token for a different tenant under the same organization must still be rejected. The tenant_id claim is checked AFTER signature verification succeeds.

Deliberately does NOT use firebase/php-jwt's CachedKeySet convenience class — it requires a PSR-18 client + PSR-17 request factory + PSR-6 cache pool, a dependency chain D-07 explicitly avoids. This hand-rolled TTL cache mirrors every sibling SDK's own JWKS-cache shape (e.g. the Python SDK's _jwks.py).

verify() never throws on attacker-controlled token input — malformed/short/ non-3-part tokens, unknown algorithms, unknown kids, and bad signatures all return null (fail closed). The only thrown exception is the ext-sodium-missing guard, which is an environment/deployment misconfiguration, not attacker input.

Table of Contents

Methods

__construct()  : mixed
verify()  : array<string, mixed>|null

Methods

__construct()

public __construct(ClientInterface $http, string $baseUrl[, int $cacheTtlSeconds = 300 ]) : mixed
Parameters
$http : ClientInterface
$baseUrl : string
$cacheTtlSeconds : int = 300

verify()

public verify(string $jwt, string $expectedTenantId) : array<string, mixed>|null
Parameters
$jwt : string
$expectedTenantId : string
Return values
array<string, mixed>|null

Verified claims, or null on any verification failure (never throws on attacker input).

On this page

Search results