Client attestation challenges
Issuer2 can require a signed challenge inside the client-attestation proof of possession. Challenges are off unless you enable them. Key attestations inside credential proofs are a different setting (keyAttestationConfig). Credential c_nonce values from /openid4vci/nonce are a third setting. None of the three replaces the others.
This documents walt-id/waltid-identity#2421 (WAL-1587).
Enable challenges
Add challenge on the client-attestation method in clientAuthenticationConfig.supportedMethods, inside issuer-service.conf, and restart Issuer2:
clientAuthenticationConfig {
supportedMethods = [
{
type = "client-attestation"
config { ... }
challenge {
lifetimeSeconds = 300
}
}
]
}
| Value | Effect |
|---|---|
challenge omitted, or challenge = null | No challenge endpoint, no challenge_endpoint in discovery, and no challenge check |
challenge = {} | Challenges on, with a 300-second lifetime |
lifetimeSeconds | A positive number of seconds. The signed challenge is bound to this issuer and signed with the token signing key |
Authorization server metadata, including signed_metadata when that is configured, advertises challenge_endpoint only while challenges are enabled.
Fetch a challenge
The endpoint takes no authentication and no body. It returns 404 while challenges are disabled.
curl -i -X POST http://localhost:7005/openid4vci/challenge
HTTP/1.1 200 OK
Cache-Control: no-store
{"attestation_challenge":"<signed-challenge>"}
Put that value in the challenge claim of the client-attestation proof-of-possession JWT (OAuth-Client-Attestation-PoP). The same challenge can be reused at PAR, the token endpoint, and refresh until it expires. Each request still needs a newly signed proof of possession with a fresh jti.
Retry when a challenge is missing or expired
PAR and the token endpoint answer HTTP 400 before they consume the grant:
OAuth-Client-Attestation-Challenge: <fresh-signed-challenge>
{"error":"use_attestation_challenge"}
Retry POST /openid4vci/par with the same authorization parameters and a new proof of possession whose challenge is that header. Retry POST /openid4vci/token the same way, keeping the authorization code, pre-authorized code, or refresh token. Browsers can read the header because it is exposed through CORS.
Other attestation failures keep their usual OAuth errors. A pre-authorized request that is explicitly allowed to be anonymous stays allowed.
