Skip to content

[ABCA] Implement a Challenge Endpoint - #51574

Open
Ogenbertrand wants to merge 14 commits into
keycloak:mainfrom
adorsys:issue-44769
Open

[ABCA] Implement a Challenge Endpoint#51574
Ogenbertrand wants to merge 14 commits into
keycloak:mainfrom
adorsys:issue-44769

Conversation

@Ogenbertrand

Copy link
Copy Markdown
Contributor

closes: #44769

Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>
Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>
Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>
Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>
Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>
Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>
Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>
Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>
Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>
Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>
Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>
Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>
Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>
@Ogenbertrand
Ogenbertrand requested a review from a team as a code owner August 10, 2026 11:16
Copilot AI balanced review requested due to automatic review settings August 10, 2026 11:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements the ABCA challenge endpoint and challenge validation lifecycle.

Changes:

  • Adds challenge endpoint discovery and response support.
  • Validates and consumes challenges in PoP JWTs.
  • Adds test utilities and integration coverage.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/utils-shared/.../Endpoints.java Adds challenge endpoint URL.
tests/utils-shared/.../ClientAttestationChallengeResponse.java Parses challenge responses.
tests/utils-shared/.../ClientAttestationChallengeRequest.java Sends challenge requests.
tests/utils-shared/.../AbstractOAuthClient.java Exposes the request helper.
tests/base/.../OID4VCBasicWallet.java Adds challenges to PoP JWTs.
tests/base/.../OIDCAttestationBasedClientAuthenticationTest.java Tests endpoint and lifecycle behavior.
services/.../OIDCWellKnownProvider.java Advertises challenge endpoint metadata.
services/.../OIDCLoginProtocolService.java Registers the endpoint route.
services/.../ClientAttestationChallengeEndpoint.java Implements challenge issuance.
services/.../ClientAttestationChallengeResponse.java Defines the response model.
services/.../AttestationBasedClientAuthenticator.java Validates and consumes challenges.
core/.../OIDCConfigurationRepresentation.java Adds challenge endpoint metadata.
core/.../OAuthErrorException.java Adds the challenge-required error code.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Signed-off-by: Ogenbertrand <ogenbertrand@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (3)

services/src/main/java/org/keycloak/protocol/oidc/endpoints/ClientAttestationChallengeEndpoint.java:95

  • The successful response bypasses Cors, so a cross-origin wallet receives no Access-Control-Allow-Origin and cannot read either the challenge body or its custom header. Apply CORS to the success response (the SSL error path already does this) and expose the challenge header.
        return Response.ok(challengeResponse)
                .header(HttpHeaders.CACHE_CONTROL, "no-store")
                .header("Pragma", "no-cache")
                .header(HttpHeaders.DATE, DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(ZoneOffset.UTC)))
                .header(AttestationBasedClientAuthenticator.OAUTH_CLIENT_ATTESTATION_CHALLENGE_HEADER, challenge)

services/src/main/java/org/keycloak/authentication/authenticators/client/AttestationBasedClientAuthenticator.java:146

  • Browser clients cannot read this fresh challenge: TokenEndpoint.java:125 exposes only Access-Control-Allow-Methods, and AuthorizeClientUtil applies that CORS configuration to this authentication failure. Add OAuth-Client-Attestation-Challenge to the token endpoint's exposed headers so the required retry flow works cross-origin.
            Response response = Response.fromResponse(ClientAuthUtil.errorResponse(BAD_REQUEST.getStatusCode(), USE_ATTESTATION_CHALLENGE, ex.getMessage()))
                    .header(OAUTH_CLIENT_ATTESTATION_CHALLENGE_HEADER, ex.getChallenge())

tests/base/src/test/java/org/keycloak/tests/oid4vc/abca/OIDCAttestationBasedClientAuthenticationTest.java:287

  • The lifecycle tests cover reuse but not expiration, although rejecting expired challenges and returning use_attestation_challenge with a fresh header is an explicit requirement. Add an expired-challenge integration case, for example by temporarily setting the nonce lifetime negative as existing OID4VC tests do.
    @Test
    public void testClientAttestationChallengeCannotBeReused() {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ABCA] Implement a Challenge Endpoint

2 participants