AXIAM PHP SDK

IdTokenValidator
in package

FinalYes

ID-token claim validation — CONTRACT.md §12.4, OIDC Core §3.1.3.7.

PURE logic only: no network, no JWT decoding, no crypto beyond a constant-time compare. The signature half of §12.4 (rules 1–2: alg allowlist, kid lookup, Ed25519 verification, single JWKS re-fetch) lives in JwksVerifier::verifyIdTokenSignature() — the SAME verifier the §10 middleware already uses (§12 forbids forking it). This class holds rules 3–6 (issuer, audience, time, nonce) plus the reason-code vocabulary, so both halves can be unit-tested independently, mirroring the TypeScript reference's oidcIdToken.ts/node/jwks.ts split.

Every failure raises AuthError carrying one of the seven stable reason codes below (CONTRACT.md §12.3 rule 3). Rule 7 (all-or-nothing discard) is enforced by the caller — AxiamClient::oidcExchange() never returns a token set whose ID token failed here, so access_token/refresh_token from the same response are dropped with it.

Table of Contents

Constants

ID_TOKEN_ALG  : mixed = 'EdDSA'
§12.4 rule 1 — the only algorithm this SDK accepts for an ID token.
MAX_CLOCK_SKEW_SEC  : mixed = 60
Maximum (and default) permitted clock skew in seconds for ID-token time claims.
REASON_INVALID_ALG  : mixed = 'invalid_alg'
REASON_INVALID_AUDIENCE  : mixed = 'invalid_audience'
REASON_INVALID_ISSUER  : mixed = 'invalid_issuer'
REASON_INVALID_SIGNATURE  : mixed = 'invalid_signature'
REASON_NONCE_MISMATCH  : mixed = 'nonce_mismatch'
REASON_TOKEN_EXPIRED  : mixed = 'token_expired'
REASON_UNKNOWN_KID  : mixed = 'unknown_kid'

Methods

checkClaims()  : array<string, mixed>
§12.4 rules 3–6 — issuer, audience, time and nonce checks over an already-signature-verified claim set. Returns the claims unchanged on success; throws the matching {@see AuthError} reason code on the first failure.
constantTimeEquals()  : bool
Constant-time string equality, used for the `nonce` comparison §12.4 rule 6 requires. Mirrors {@see \Axiam\Sdk\Amqp\Hmac::verify()}'s use of `hash_equals()`.
failure()  : AuthError
Build the `AuthError` for a §12.4 failure: a stable machine-readable `$reason` code plus a human-readable message that — per §12.3 rule 3 and §2's construction rules — never embeds the token, a claim value that could carry secret material, or the expected nonce.
resolveClockSkewSec()  : int
Resolve the effective clock skew: the caller's value clamped into `[0, MAX_CLOCK_SKEW_SEC]`, or the maximum when unset.

Constants

ID_TOKEN_ALG

§12.4 rule 1 — the only algorithm this SDK accepts for an ID token.

public mixed ID_TOKEN_ALG = 'EdDSA'

MAX_CLOCK_SKEW_SEC

Maximum (and default) permitted clock skew in seconds for ID-token time claims.

public mixed MAX_CLOCK_SKEW_SEC = 60

CONTRACT.md §12.4 rule 5 caps this at 60s and forbids any configuration above the bound.

REASON_INVALID_AUDIENCE

public mixed REASON_INVALID_AUDIENCE = 'invalid_audience'

REASON_INVALID_ISSUER

public mixed REASON_INVALID_ISSUER = 'invalid_issuer'

REASON_INVALID_SIGNATURE

public mixed REASON_INVALID_SIGNATURE = 'invalid_signature'

REASON_NONCE_MISMATCH

public mixed REASON_NONCE_MISMATCH = 'nonce_mismatch'

REASON_TOKEN_EXPIRED

public mixed REASON_TOKEN_EXPIRED = 'token_expired'

Methods

checkClaims()

§12.4 rules 3–6 — issuer, audience, time and nonce checks over an already-signature-verified claim set. Returns the claims unchanged on success; throws the matching {@see AuthError} reason code on the first failure.

public static checkClaims(array<string, mixed> $claims, string $issuer, string $clientId[, string|null $nonce = null ][, int|null $clockSkewSec = null ][, int|null $nowSec = null ]) : array<string, mixed>
Parameters
$claims : array<string, mixed>

The verified JWT payload.

$issuer : string

The discovery document's issuer (§12.4 rule 3).

$clientId : string

The relying party's own client_id (§12.4 rule 4).

$nonce : string|null = null

The nonce to check against, or null to skip rule 6 (oidcRefresh/loginClientCredentials).

$clockSkewSec : int|null = null

Permitted clock skew in seconds; clamped to self::MAX_CLOCK_SKEW_SEC.

$nowSec : int|null = null

Current time in epoch seconds — injectable so tests can pin it.

Return values
array<string, mixed>

constantTimeEquals()

Constant-time string equality, used for the `nonce` comparison §12.4 rule 6 requires. Mirrors {@see \Axiam\Sdk\Amqp\Hmac::verify()}'s use of `hash_equals()`.

public static constantTimeEquals(string $a, string $b) : bool
Parameters
$a : string
$b : string
Return values
bool

failure()

Build the `AuthError` for a §12.4 failure: a stable machine-readable `$reason` code plus a human-readable message that — per §12.3 rule 3 and §2's construction rules — never embeds the token, a claim value that could carry secret material, or the expected nonce.

public static failure(string $reason, string $message) : AuthError
Parameters
$reason : string
$message : string
Return values
AuthError

resolveClockSkewSec()

Resolve the effective clock skew: the caller's value clamped into `[0, MAX_CLOCK_SKEW_SEC]`, or the maximum when unset.

public static resolveClockSkewSec(int|null $clockSkewSec) : int
Parameters
$clockSkewSec : int|null
Return values
int
On this page

Search results