Skip to content

Localize WebAuthn registration verification errors#51012

Open
AkashKumar7902 wants to merge 3 commits into
keycloak:mainfrom
AkashKumar7902:agent/localize-webauthn-registration-errors
Open

Localize WebAuthn registration verification errors#51012
AkashKumar7902 wants to merge 3 commits into
keycloak:mainfrom
AkashKumar7902:agent/localize-webauthn-registration-errors

Conversation

@AkashKumar7902

@AkashKumar7902 AkashKumar7902 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • map WebAuthn4J user-presence and user-verification registration exceptions to Keycloak login-theme message keys
  • retain the original WebAuthn4J details in debug logs and event details
  • add English source messages and full-stack integration coverage for the reported user-verification path and the user-presence mapping

Motivation

When user verification is required but the authenticator does not verify the user, Keycloak currently renders a localized registration-error prefix followed by WebAuthn4J's English developer-facing exception text. This resolves a Keycloak message key for the user-facing detail while preserving the original diagnostic for operators.

Only WebAuthn4J exception types that represent a single failure reason are mapped. Other WebAuthn exception types, browser-originated registration errors, and the authentication path are unchanged.

Testing

Automated:

  • ./mvnw test -f tests/webauthn/pom.xml -Dtest=WebAuthnPolicyComplianceTest#tamperedUserPresence — 1 test passed
  • ./mvnw test -f tests/webauthn/pom.xml -Dtest=WebAuthnPolicyComplianceTest#tamperedUserVerification — 1 test passed
  • ./mvnw test -f tests/webauthn/pom.xml -Dtest=WebAuthnPolicyComplianceTest — 9 tests passed
  • ./mvnw -pl quarkus/dist -am -DskipTests -DskipTestsuite -DskipExamples package — 53-module reactor passed
  • ./mvnw -pl services,themes,tests/webauthn -DskipTests spotless:check
  • git diff --check

Manual:

  • Built the runnable distribution from 45554ad0, started it with a disposable H2 realm, and drove registration with a standalone headless Chrome client. A valid credential was accepted; after clearing the UP flag from a browser-generated credential before submission, Keycloak rendered “Failed to register your Passkey. User presence is required.”

Documentation

Not applicable; this changes an existing error diagnostic and introduces no configuration or workflow change.

AI disclosure

I used OpenAI Codex agents to assist with repository analysis, implementation, tests, and review of this change. I reviewed, understand, and can explain and revise every submitted change.

Closes #44963

@AkashKumar7902
AkashKumar7902 marked this pull request as ready for review July 18, 2026 19:38
@AkashKumar7902
AkashKumar7902 requested review from a team as code owners July 18, 2026 19:38
Copilot AI review requested due to automatic review settings July 18, 2026 19:38

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

Localizes WebAuthn registration errors for missing user presence or verification while retaining diagnostic details.

Changes:

  • Maps WebAuthn4J exceptions to login-theme message keys.
  • Adds English and German messages.
  • Adds unit coverage for mapped and fallback exceptions.

Reviewed changes

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

Show a summary per file
File Description
themes/.../messages_en.properties Adds English error messages.
themes/.../messages_de.properties Adds German translations.
WebAuthnRegisterTest.java Tests exception mappings and fallback.
Messages.java Defines the new message keys.
WebAuthnRegister.java Localizes user-facing errors while preserving diagnostics.

@ahus1

ahus1 commented Jul 20, 2026

Copy link
Copy Markdown
Member

Thank you for the pull request. Instead of a unit test, can you please provide an integration test?

There is no need to add a German translation in this PR. This is better handled in the Weblate project. As you're overriding the English text already, you should be able to test this without the German text.

In the code where you map an exception to a text, it would be good to add a note that this is only possible for those exceptions that map to a single message in the webauthn4j code (unfortunately, some of them don't).

Map user-presence and user-verification exceptions to theme messages while retaining the original WebAuthn4J diagnostics in logs and event details.

Closes keycloak#44963

Signed-off-by: Akash Kumar <meakash7902@gmail.com>
Copilot AI review requested due to automatic review settings July 20, 2026 07:28
@AkashKumar7902
AkashKumar7902 force-pushed the agent/localize-webauthn-registration-errors branch from 2814a7b to 2ef6614 Compare July 20, 2026 07:28
@AkashKumar7902

Copy link
Copy Markdown
Contributor Author

Thanks for the review. I addressed all three points in 2ef66142:

  • replaced the unit test with the existing full-stack WebAuthnPolicyComplianceTest#tamperedUserVerification coverage, which reaches the server-side UserNotVerifiedException and asserts the rendered English theme message;
  • removed the German translations so they can be handled through Weblate;
  • documented why only WebAuthn4J exceptions representing a single failure reason can be mapped safely.

I also rebased onto current main. The focused integration test passes, the full WebAuthnPolicyComplianceTest class passes (8/8), and Spotless/diff checks pass.

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 4 out of 4 changed files in this pull request and generated 1 comment.

@ahus1 ahus1 self-assigned this Jul 20, 2026
@keycloak-github-bot

Copy link
Copy Markdown

Unreported flaky test detected

If the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR.

org.keycloak.testsuite.forms.MultipleTabsLoginTest#multipleTabsParallelLoginTestWithAuthSessionExpiredAndRegisterClick

Keycloak CI - Forms IT (firefox)

org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
	at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:36)
...

Report flaky test

@keycloak-github-bot keycloak-github-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unreported flaky test detected, please review

Copilot AI review requested due to automatic review settings July 20, 2026 10:46

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 4 out of 4 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

services/src/main/java/org/keycloak/authentication/requiredactions/WebAuthnRegister.java:463

  • The new UserNotPresentException branch has no corresponding test; the updated integration test only exercises UserNotVerifiedException. Add a registration case (or focused unit test) that triggers a missing UP flag and asserts the localized user-presence message.
        if (exception instanceof UserNotPresentException) {
            return WEBAUTHN_ERROR_USER_NOT_PRESENT;

@ahus1

ahus1 commented Jul 20, 2026

Copy link
Copy Markdown
Member

Please avoid merging the main branch into the PR or rebasing the PR unless there are merge conflicts reported by GitHub or a reviewer asks you for a rebase. This prevents spamming reviewers with notifications and saves minutes on the GitHub actions CI. Thanks!

@keycloak-github-bot

Copy link
Copy Markdown

Unreported flaky test detected

If the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR.

org.keycloak.testsuite.forms.MultipleTabsLoginTest#multipleTabsParallelLoginTestWithAuthSessionExpiredAndRegisterClick

Keycloak CI - Forms IT (chrome)

org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
	at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:36)
...

Report flaky test

org.keycloak.testsuite.oauth.ClientAuthPostMethodTest#testPostAuthenticationNotAllowedWhenBasicRequested

Keycloak CI - Base IT (6)

java.lang.NullPointerException: Cannot read field "features" because the return value of "org.keycloak.common.Profile.getInstance()" is null
	at org.keycloak.common.Profile.isFeatureEnabled(Profile.java:534)
	at org.keycloak.protocol.oidc.OIDCClientSecretConfigWrapper.<init>(OIDCClientSecretConfigWrapper.java:41)
	at org.keycloak.protocol.oidc.OIDCClientSecretConfigWrapper.fromClientRepresentation(OIDCClientSecretConfigWrapper.java:49)
	at org.keycloak.testsuite.oauth.ClientAuthPostMethodTest.testPostAuthenticationNotAllowedWhenBasicRequested(ClientAuthPostMethodTest.java:141)
...

Report flaky test

org.keycloak.testsuite.oauth.ClientAuthPostMethodTest#testBasicAuthenticationNotAllowedWhenPostRequested

Keycloak CI - Base IT (6)

java.lang.NullPointerException: Cannot read field "features" because the return value of "org.keycloak.common.Profile.getInstance()" is null
	at org.keycloak.common.Profile.isFeatureEnabled(Profile.java:534)
	at org.keycloak.protocol.oidc.OIDCClientSecretConfigWrapper.<init>(OIDCClientSecretConfigWrapper.java:41)
	at org.keycloak.protocol.oidc.OIDCClientSecretConfigWrapper.fromClientRepresentation(OIDCClientSecretConfigWrapper.java:49)
	at org.keycloak.testsuite.oauth.ClientAuthPostMethodTest.testBasicAuthenticationNotAllowedWhenPostRequested(ClientAuthPostMethodTest.java:112)
...

Report flaky test

org.keycloak.testsuite.forms.MultipleTabsLoginTest#multipleTabsParallelLoginTestWithAuthSessionExpiredAndRegisterClick

Keycloak CI - Forms IT (firefox)

org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
	at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:36)
...

Report flaky test

org.keycloak.testsuite.forms.BrowserFlowTest#testUserWithOneAdditionalFactorOtpSuccess

Keycloak CI - Base IT (5)

org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
	at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:36)
...

Report flaky test

@keycloak-github-bot keycloak-github-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unreported flaky test detected, please review

Clear the UP flag in a browser-generated attestation so the integration suite covers the localized UserNotPresentException mapping.

Signed-off-by: Akash Kumar <meakash7902@gmail.com>
Copilot AI review requested due to automatic review settings July 21, 2026 08:55
@AkashKumar7902

Copy link
Copy Markdown
Contributor Author

Understood—thanks for the guidance. I left the branch history as-is; this update was a normal fast-forward push containing only the requested UP-coverage test. I won’t merge or rebase main again unless GitHub reports conflicts or a reviewer asks.

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 4 out of 4 changed files in this pull request and generated no new comments.

@keycloak-github-bot keycloak-github-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unreported flaky test detected, please review

@keycloak-github-bot

Copy link
Copy Markdown

Unreported flaky test detected

If the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR.

org.keycloak.testsuite.forms.BrowserFlowTest#testUserWithOneAdditionalFactorOtpSuccess

Keycloak CI - Base IT (5)

org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
	at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:36)
...

Report flaky test

org.keycloak.testsuite.forms.MultipleTabsLoginTest#testEmptyBaseUrl

Keycloak CI - Forms IT (firefox)

org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
	at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:36)
...

Report flaky test

org.keycloak.testsuite.forms.MultipleTabsLoginTest#multipleTabsParallelLoginTestWithAuthSessionExpiredInTheMiddle

Keycloak CI - Forms IT (firefox)

org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertTrue.failNotTrue(AssertTrue.java:63)
	at org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:36)
...

Report flaky test

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PassKey "User verification requirement" error's are not translated

3 participants