At the resource server, inspect the access token's acr claim and max_age-derived auth_time; if the required ACR level or recency is not met, return HTTP 401 with a WWW-Authenticate header containing error=insufficient_user_authentication and acr_values/max_age parameters
The client receives the 401 and parses the WWW-Authenticate challenge to extract the required acr_values and max_age
The client initiates a new authorization request to the AS including the acr_values and max_age from the challenge; use PAR for this request if the AS supports it
The AS performs the required step-up (e.g. prompt MFA, trigger passkey authentication) and issues a new access token whose acr and auth_time satisfy the requirements
The client retries the original resource request with the new access token; the resource server verifies the acr and auth_time claims on the new token before granting access
Implement acr_values in the AS: map each ACR value to a specific authentication policy (e.g. urn:mace:incommon:iap:silver = password, urn:mace:incommon:iap:gold = passkey + hardware token)
Known gotchas
The WWW-Authenticate header parameters acr_values and max_age are OAuth-specific extensions beyond RFC 6750; clients that only implement RFC 6750 Bearer token handling will not parse them — ensure your client library supports RFC 9470
If the access token lacks an acr claim at all (e.g. it was issued by an AS that doesn't emit acr), the resource server cannot enforce step-up based on ACR — define a fallback policy for tokens without acr
max_age in the step-up challenge is measured in seconds from the auth_time claim in the token; clock skew between the RS and AS can cause spurious step-up triggers — apply a reasonable tolerance window
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp