Skip to content

Adding and improving WebAuthn error messages#50654

Merged
rmartinc merged 2 commits into
keycloak:mainfrom
uzmamansoor09:22524
Jul 24, 2026
Merged

Adding and improving WebAuthn error messages#50654
rmartinc merged 2 commits into
keycloak:mainfrom
uzmamansoor09:22524

Conversation

@uzmamansoor09

Copy link
Copy Markdown
Contributor

Closes #22524

Improving how WebAuthn error messages are handled and displayed to the end-user.
Introducing error mapping for the most common WebAuthn error scenarios (such as user cancellation, an authenticator already being registered, operation timeouts, or blocked AAGUIDs) to individual message keys. For generic or unexpected errors, a generic message is shown instead, while the specific technical details from webauthn4j are written to the server logs.

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

This PR improves how WebAuthn/Passkey errors are presented to end users by mapping common browser/API and policy-related failures to dedicated, localizable message keys, while avoiding exposing raw technical exception text in the UI.

Changes:

  • Replaces WebAuthn UI error strings that previously surfaced raw {0} technical details with localized, user-friendly messages.
  • Introduces message-key mapping for common browser WebAuthn API error scenarios and for specific registration policy violations (AAGUID/attestation/attachment).
  • Updates integration tests to assert the new end-user-facing messages.

Reviewed changes

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

Show a summary per file
File Description
themes/src/main/resources/theme/base/login/messages/messages_en.properties Updates existing WebAuthn error messages and adds new localized keys for common scenarios.
services/src/main/java/org/keycloak/services/messages/Messages.java Adds new message-key constants for specific WebAuthn error cases.
services/src/main/java/org/keycloak/authentication/requiredactions/WebAuthnRegister.java Maps browser errors to specific message keys; introduces policy exception type carrying a localizable message key; removes technical details from UI error rendering.
services/src/main/java/org/keycloak/authentication/authenticators/browser/WebAuthnAuthenticator.java Maps browser .get() errors to specific message keys and ensures UI no longer displays raw technical details.
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/webauthn/registration/WebAuthnOtherSettingsTest.java Updates existing assertions and adds coverage for new browser API error-to-message mapping.
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/webauthn/registration/AuthAttachmentRegisterTest.java Updates assertions to validate the new attachment mismatch end-user message.

@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.BruteForceTest#testExceedMaxTemporaryLockouts

Keycloak CI - Base IT (5)

org.opentest4j.AssertionFailedError: Expected error event ==> 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

@uzmamansoor09
uzmamansoor09 force-pushed the 22524 branch 5 times, most recently from 874903d to a4f9dfd Compare July 13, 2026 16:04
@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.adapter.servlet.SAMLServletAdapterTest#salesPostSigPersistentTest

Keycloak CI - Adapter IT Strict Cookies

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.adapter.servlet.SAMLServletAdapterTest#salesMetadataTest

Keycloak CI - Adapter IT Strict Cookies

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.adapter.servlet.SAMLServletAdapterTest#employeeSigPostNoIdpKeyTestNoKeyNameInKeyInfo

Keycloak CI - Adapter IT Strict Cookies

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.adapter.servlet.SAMLServletAdapterTest#salesPostEncTest

Keycloak CI - Adapter IT Strict Cookies

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

@uzmamansoor09
uzmamansoor09 force-pushed the 22524 branch 2 times, most recently from 57852b3 to b07000e Compare July 13, 2026 21:14
@uzmamansoor09
uzmamansoor09 marked this pull request as ready for review July 14, 2026 08:47
@uzmamansoor09
uzmamansoor09 requested a review from a team as a code owner July 14, 2026 08:47
Copilot AI review requested due to automatic review settings July 14, 2026 08:47
@uzmamansoor09
uzmamansoor09 requested review from a team as code owners July 14, 2026 08:47

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

Copilot AI review requested due to automatic review settings July 14, 2026 08:53

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

Copilot AI review requested due to automatic review settings July 15, 2026 16:36

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

Comment thread themes/src/main/resources/theme/base/login/messages/messages_en.properties Outdated
Copilot AI review requested due to automatic review settings July 15, 2026 19:05

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

@uzmamansoor09
uzmamansoor09 marked this pull request as draft July 15, 2026 19:15
@uzmamansoor09
uzmamansoor09 force-pushed the 22524 branch 2 times, most recently from 146eba1 to bcee042 Compare July 15, 2026 19:29
@uzmamansoor09
uzmamansoor09 marked this pull request as ready for review July 15, 2026 19:29
Copilot AI review requested due to automatic review settings July 15, 2026 19:29

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

@rmartinc rmartinc 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.

Thanks @uzmamansoor09! Looks good but I think we can improve the situation more:

  • Adding the option to pass parameters to the messages (for example to show the invalid aaguid or the invalid attachment). We can even add the original webauthn message for some of them if we consider necessary to ad the details. But for the moment it's OK. I just want to have the ability to use parameters.
  • Catching the ModelDuplicateException in the registration class and creating another specific error for the duplcate device as before.
  • I think we can remove a lot of the warning messages you are adding because the event is already showing the previous detailed message. You can remove or change to debug all of them.

I have create a new commit named test in this branch: https://github.com/rmartinc/keycloak/tree/refs/heads/pr-50654 (I'm passing the CI now in GitHub, but locally the webauthn jobs passed OK). You can cherry-pick this commit and tune or change it as you want. I wanted to test if we can pass parameters to improve the messages. This gives us more freedom to create better messages for the future if needed.

@mabartos

Copy link
Copy Markdown
Member

Hi! Would be also good to check this PR that also improves the error message and provides the i18n ability: #51012

It'd be good to think about the possibility of localizing the messages and decide whether the PR should be a follow-up, or it should somehow influence this PR. Thanks!

I'll do the actual review later.

Signed-off-by: uzmamansoor09 <Uzma.Mansoor@ibm.com>

# Conflicts:
#	testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/webauthn/WebAuthnIdlessTest.java
#	testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/webauthn/registration/AttestationConveyanceRegisterTest.java
#	testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/webauthn/registration/AuthAttachmentRegisterTest.java
Signed-off-by: uzmamansoor09 <Uzma.Mansoor@ibm.com>

@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.MultipleTabsLoginTest#testLoginPageRefresh

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

@rmartinc rmartinc 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.

Thanks @uzmamansoor09! As we chatted the issue #44963 will be managed as a follow-up. We can use the webauthn4j exception thrown in the authentication and registration to give a different message per exception (or just the most commons exceptions). Approving and merging this one for the moment.

result = user.credentialManager().isValid(cred);
} catch (WebAuthnException wae) {
logger.debug("WebAuthn authentication verification failed.", wae);
setErrorResponse(context, WEBAUTHN_ERROR_AUTH_VERIFICATION, wae.getMessage());

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.

As commented by Martin and in #44963, here we can use the WebAuthnException type to give detailed messages (maybe not all of them, but the common ones). But #44963 will be managed as a follow-up.

} catch (WebAuthnException wae) {
if (logger.isDebugEnabled()) logger.debug(wae.getMessage(), wae);
logger.debug("WebAuthn registration failed.", wae);
setErrorResponse(context, WEBAUTHN_ERROR_REGISTRATION, wae.getMessage(), originalEventType);

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.

Same here, the WebAuthnExceptioncan be used to set a more detailed message instead of the generic one. But there will be another PR for that.

@rmartinc
rmartinc merged commit 2bbce40 into keycloak:main Jul 24, 2026
91 checks passed
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.

Improve WebAuthn error messages

4 participants