Skip to content

webauthnRegister.js: sync with upstream - #7

Open
rolandspannagl wants to merge 2 commits into
keycloakify:mainfrom
rolandspannagl:fix/webauthn-register-attachment-residentkey
Open

webauthnRegister.js: sync with upstream#7
rolandspannagl wants to merge 2 commits into
keycloakify:mainfrom
rolandspannagl:fix/webauthn-register-attachment-residentkey

Conversation

@rolandspannagl

@rolandspannagl rolandspannagl commented Aug 12, 2026

Copy link
Copy Markdown

I found two issues while running recent Keycloak with WebAuthn:

  • registerByWebAuthn() ignored PublicKeyCredential.authenticatorAttachment, so the registration request didn't include it.
  • Only legacy requireResidentKey was handled in authenticatorSelection, so the new setting residentKey was ignored.

This commit brings webauthnRegister.js in sync with current upstream Keycloak's version and so fixes both issues.

Summary by CodeRabbit

  • New Features

    • Improved WebAuthn registration compatibility by supporting resident key preferences across current and legacy settings.
    • Registration results now retain authenticator attachment details when available.
  • Bug Fixes

    • Improved handling of whitespace and fallback registration preferences for more reliable WebAuthn setup.

I found two issues while running recent Keycloak with WebAuthn:
- registerByWebAuthn() ignored PublicKeyCredential.authenticatorAttachment, so the registration request didn't include it.
- Only legacy requireResidentKey was handled in authenticatorSelection, so the new setting residentKey was ignored.

This commit brings webauthnRegister.js in sync with current upstream Keycloak's version and so fixes both issues.
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9692e1f9-73dc-4376-a376-5923c2c695c0

📥 Commits

Reviewing files that changed from the base of the PR and between 63d11e6 and 77a8d6f.

📒 Files selected for processing (3)
  • keycloak-theme/login/pages/webauthn-register/useScript.tsx
  • src/core/KcContext/KcContext.ts
  • src/core/KcContext/kcContextMocks.ts

📝 Walkthrough

Walkthrough

WebAuthn registration now supports the residentKey option, maintains requireResidentKey compatibility, and stores authenticatorAttachment after successful registration.

Changes

WebAuthn registration

Layer / File(s) Summary
Registration context and wiring
src/core/KcContext/KcContext.ts, src/core/KcContext/kcContextMocks.ts, keycloak-theme/login/pages/webauthn-register/useScript.tsx
The registration context type and mock include residentKey. The generated registration input passes this option to registerByWebAuthn.
Registration options and result handling
keycloak-theme/public/login/js/webauthnRegister.js
Registration prioritizes residentKey, synchronizes requireResidentKey, falls back to deprecated input values, and stores authenticatorAttachment when present.

Estimated code review effort: 2 (Simple) | ~10 minutes

Mergeability Score: ⚪ Minimal · up to 77a8d

This localized change adds the missing WebAuthn registration settings for authenticator attachment and resident keys; no actionable merge-blocking risk remains after normal checks and review.

Possibly related issues

  • keycloakify/keycloakify#1050 — Addresses the WebAuthn residentKey and requireResidentKey compatibility issue.

Suggested reviewers: garronej

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: synchronizing webauthnRegister.js with the upstream Keycloak implementation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@keycloak-theme/public/login/js/webauthnRegister.js`:
- Around line 34-46: Add residentKey to the WebauthnRegister context contract
and the registration input object consumed by webauthnRegister.js. In the
fallback branch around input.requireResidentKey, normalize an absent value to
"not specified" before evaluating it, so fallback is skipped unless the
deprecated option is explicitly provided.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 66c83bbe-97e9-45e3-86e2-39e149372929

📥 Commits

Reviewing files that changed from the base of the PR and between 2a9da59 and 63d11e6.

📒 Files selected for processing (1)
  • keycloak-theme/public/login/js/webauthnRegister.js

Comment on lines +34 to +46
if (input.residentKey && input.residentKey !== 'not specified') {
// residentKey is the current spec field and the source of truth. requireResidentKey is
// deprecated but still set for older clients: it is true iff residentKey is 'required'.
authenticatorSelection.residentKey = input.residentKey;
authenticatorSelection.requireResidentKey = input.residentKey === 'required';
isAuthenticatorSelectionSpecified = true;
} else if (input.requireResidentKey !== 'not specified') {
// fall back to the deprecated option when residentKey is not specified
if (input.requireResidentKey === 'Yes') {
authenticatorSelection.residentKey = 'required';
authenticatorSelection.requireResidentKey = true;
} else {
authenticatorSelection.residentKey = 'discouraged';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- caller ---'
cat -n keycloak-theme/login/pages/webauthn-register/useScript.tsx | sed -n '1,90p'

printf '%s\n' '--- webauthnRegister.js relevant sections ---'
cat -n keycloak-theme/public/login/js/webauthnRegister.js | sed -n '1,75p'
cat -n keycloak-theme/public/login/js/webauthnRegister.js | sed -n '120,155p'

printf '%s\n' '--- references ---'
rg -n -C 3 'registerByWebAuthn|residentKey|requireResidentKey' keycloak-theme/login keycloak-theme/public/login/js

Repository: keycloakify/login-ui

Length of output: 14311


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- resident-key definitions and context fields ---'
rg -n -C 4 'residentKey|requireResidentKey|webauthn-register\.ftl|WebAuthnRegister' . \
  -g '!node_modules' -g '!dist' -g '!build'

printf '%s\n' '--- candidate context/type files ---'
git ls-files | rg '(^|/)(KcContext|kcContext|webauthn|WebAuthn|login).*'

printf '%s\n' '--- exact branch probe ---'
node - <<'JS'
function selection(input) {
  const authenticatorSelection = {};
  let specified = false;

  if (input.residentKey && input.residentKey !== "not specified") {
    authenticatorSelection.residentKey = input.residentKey;
    authenticatorSelection.requireResidentKey = input.residentKey === "required";
    specified = true;
  } else if (input.requireResidentKey !== "not specified") {
    if (input.requireResidentKey === "Yes") {
      authenticatorSelection.residentKey = "required";
      authenticatorSelection.requireResidentKey = true;
    } else {
      authenticatorSelection.residentKey = "discouraged";
      authenticatorSelection.requireResidentKey = false;
    }
    specified = true;
  }

  return specified ? authenticatorSelection : undefined;
}

for (const input of [
  {},
  { requireResidentKey: undefined },
  { requireResidentKey: "not specified" },
  { requireResidentKey: "No" },
  { requireResidentKey: "Yes" },
  { residentKey: "required", requireResidentKey: "No" }
]) {
  console.log(JSON.stringify(input), "=>", JSON.stringify(selection(input)));
}
JS

Repository: keycloakify/login-ui

Length of output: 21931


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- WebauthnRegister context type ---'
cat -n src/core/KcContext/KcContext.ts | sed -n '405,435p'

printf '%s\n' '--- WebauthnRegister mocks ---'
cat -n src/core/KcContext/kcContextMocks.ts | sed -n '515,540p'
cat -n src/core/KcContext/getKcContextMock.ts | sed -n '1,80p'

printf '%s\n' '--- upstream/default-theme generator ---'
cat -n scripts/shared/downloadKeycloakDefaultTheme.overridable.ts | sed -n '380,445p'
rg -n -C 5 'requireResidentKey|residentKey' scripts src keycloak-theme

Repository: keycloakify/login-ui

Length of output: 15363


🌐 Web query:

Keycloak webauthn-register.ftl requireResidentKey residentKey values "not specified" "Yes"

💡 Result:

In Keycloak, the requireResidentKey property historically used in webauthn-register.ftl is a legacy boolean field that has been superseded by the residentKey property in the WebAuthn specification [1][2]. Keycloak has historically encountered issues where the "Require discoverable credential" policy setting was not correctly propagated to the frontend, sometimes resulting in requireResidentKey being incorrectly passed as a string value (e.g., "Yes") rather than a boolean or the appropriate residentKey string value (such as "required" or "preferred") [1][3]. Keycloak has been actively transitioning to using residentKey to align with modern WebAuthn standards [3]. Recent updates and issue resolutions (such as Issue #42513) have focused on replacing the deprecated requireResidentKey with the residentKey property in registration requests to improve compatibility with passkeys and modern authenticators [3]. For current implementations, relying on the legacy requireResidentKey boolean is discouraged, as it cannot express the "preferred" option and may be ignored or handled inconsistently by modern platforms [2]. Developers should refer to the latest Keycloak documentation and release notes—particularly for versions 26.4 and newer—regarding improved passkey and WebAuthn configuration support [4].

Citations:


🌐 Web query:

site:github.com/keycloak/keycloak webauthnRegister.js requireResidentKey residentKey

💡 Result:

In the context of the WebAuthn API and implementations like Keycloak's webauthnRegister.js, requireResidentKey is a deprecated property, whereas residentKey (often referred to in documentation as "Discoverable Credential" requirement) is the modern, preferred property [1][2][3][4]. The WebAuthn specification and current implementations have transitioned to using residentKey within the authenticatorSelection criteria of PublicKeyCredentialCreationOptions [2][5]. Key Characteristics: - Deprecation: requireResidentKey is deprecated and is being phased out in favor of residentKey [1][2][3]. - Nomenclature: The industry has moved toward the term "Discoverable Credential" to describe what was previously known as a "Resident Key" [2][4]. - Implementation Status: In systems like Keycloak, recent updates have introduced residentKey as a policy option to replace the deprecated requireResidentKey [1][6]. The older property was frequently misused or incorrectly propagated (often as a string instead of a boolean), leading to registration issues where the authenticator would not correctly generate a discoverable credential [5]. - Configuration: When configuring WebAuthn policies or registration requests, you should prioritize the residentKey parameter, which typically accepts values such as 'required', 'preferred', or 'discouraged' [2]. If you are maintaining or updating code like webauthnRegister.js, you should check for the availability of residentKey in your configuration objects and transition away from relying on requireResidentKey to ensure compatibility with modern browsers and authenticators [1][6].

Citations:


Pass residentKey through the WebAuthn registration context.

useScript.tsx supplies only requireResidentKey, and KcContext.WebauthnRegister does not declare residentKey. Add the field to the context contract and input object. Treat an absent requireResidentKey as "not specified" before applying the fallback; otherwise it produces residentKey: "discouraged".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@keycloak-theme/public/login/js/webauthnRegister.js` around lines 34 - 46, Add
residentKey to the WebauthnRegister context contract and the registration input
object consumed by webauthnRegister.js. In the fallback branch around
input.requireResidentKey, normalize an absent value to "not specified" before
evaluating it, so fallback is skipped unless the deprecated option is explicitly
provided.

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.

1 participant