feat: add WebAuthn/Passkey Phoenix components#718
feat: add WebAuthn/Passkey Phoenix components#718raul-gracia wants to merge 5 commits intoteam-alembic:mainfrom
Conversation
Adds LiveView components for the WebAuthn authentication strategy: - WebAuthn container component with register/sign-in toggle - RegistrationForm and AuthenticationForm components - Input component with identity field and submit button - ManageCredentials component for listing, renaming, deleting keys - Support component for browser capability detection - Overrides for Default and DaisyUI themes - Ships bundled JS hooks in priv/static/webauthn_hooks.js Depends on ash_authentication webauthn-strategy branch.
Dependency NoteThis PR depends on team-alembic/ash_authentication#1144 which adds the The Once that happens, the dependency in {:ash_authentication, "~> 5.0.0-rc"}There's a TODO comment in |
Adds SPDX copyright/license headers to all new WebAuthn files for REUSE compliance. The ash_authentication dependency uses a local path override because the WebAuthn strategy is not yet in the published hex package (pending team-alembic/ash_authentication#1144).
7d0e879 to
1ce2ed3
Compare
jimsynz
left a comment
There was a problem hiding this comment.
Hey @raul-gracia — thanks again for the work on this companion PR. The component hierarchy is well-structured (WebAuthn → RegistrationForm / AuthenticationForm / ManageCredentials / Support / Input), the override integration for both Default and DaisyUI themes is thorough, and the JS hooks handle the ceremony lifecycle cleanly. Having the credential management panel built-in is a real bonus.
Following on from my review on #1144, here are the items I found on the Phoenix side that need addressing before we can ship.
Security items
ManageCredentials bypasses Actions.add_credential (Medium)
ManageCredentials.handle_event("registration-attestation", ...) creates credentials directly via Ash.Changeset.for_create(:create, attrs, ash_opts) rather than going through WebAuthn.Actions.add_credential/3. This means any future validation, hooks, or security checks added to add_credential won't apply to credentials added through the management panel. Should route through the Actions module for consistency.
SVG icon override rendered with Phoenix.HTML.raw() (Low)
The register_button_icon and sign_in_button_icon overrides are rendered via Phoenix.HTML.raw(icon). The docs note these must be trusted static SVG, which is fine for normal usage. Just flagging it — if anyone builds dynamic overrides from user input (unlikely but possible), it's an XSS vector.
Functionality items
Missing component_for_strategy clause in SignIn
The diff adds strategy_style(%AshAuthentication.Strategy.WebAuthn{}) returning :form, but I don't see a corresponding component_for_strategy clause mapping WebAuthn to Components.WebAuthn. Without this, the auto-discovery flow in the SignIn component won't know which component to render for WebAuthn strategies. Needs a clause like:
defp component_for_strategy(%{strategy_module: AshAuthentication.Strategy.WebAuthn}),
do: Components.WebAuthn(or whatever the matching pattern is for Custom strategies — worth checking how the existing ones dispatch)
mix.exs local path override
The mix.exs has {:ash_authentication, path: "../ash_authentication", override: true} — this needs to be removed before merge. Should point at the hex package (with a version constraint that includes WebAuthn once #1144 lands), or at a git ref if we want to merge this before the hex release.
Test helper references Example.Accounts.User
WebAuthnHelpers.mock_webauthn_strategy/1 sets resource: Example.Accounts.User, but the test support in ash_authentication uses Example.UserWithWebAuthn. This may cause issues depending on what's available in the Phoenix repo's test support.
No end-to-end documentation guide
The module docs are solid, but a Getting Started guide covering the full setup — backend strategy + Phoenix components + JS hook registration — would help a lot with adoption. WebAuthn has more moving parts than most strategies (credential resource, JS hooks, origin configuration), so a step-by-step walkthrough would be valuable. This could be a HexDocs guide page or a section in the README.
JS hook registration is manual
Users need to import and register WebAuthnRegistrationHook, WebAuthnAuthenticationHook, and WebAuthnSupportHook in their app.js. It's documented in comments in the hooks file, but easy to miss. An Igniter generator (mentioned in the #1144 review) could automate this.
Same offer as on #1144 — these are all tractable items and I'm happy to pick up whatever you'd rather not tackle yourself. This is a really solid foundation and I'd love to get it shipped. Let me know how you'd like to split the remaining work.
- ManageCredentials now routes new credential creation through WebAuthn.Actions.add_credential/3 instead of constructing an Ash changeset directly. This keeps policies, hooks, and future validation on the credential resource in play. - Adds end-to-end WebAuthn tutorial covering backend strategy, router, JS hook registration, rp_id pitfalls, credential management, and troubleshooting. Registered in the docs extras list. - Documents the WebAuthnHelpers mock resource choice and its scope (gated UI-only tests vs real ceremony tests in the upstream repo).
Explicitly document that rp_id is a hostname only — never include scheme or port — with a comparison table covering dev/staging/prod. Adds the localhost:4000 gotcha to both the rp_id section and troubleshooting.
|
Thanks for the review @jimsynz. Pushed 58c70dc and fffadc3 addressing the items below. Using your section structure so each point is easy to track. Security itemsManageCredentials bypasses
|
# Conflicts: # lib/ash_authentication_phoenix/overrides/list.ex # mix.exs # mix.lock
Add Phoenix LiveView components for WebAuthn/Passkey authentication.
Components
Components.WebAuthn- container with register/sign-in toggleComponents.WebAuthn.RegistrationForm- passkey registration formComponents.WebAuthn.AuthenticationForm- passkey sign-in formComponents.WebAuthn.Input- identity field + submit button with WebAuthn JS hooksComponents.WebAuthn.ManageCredentials- list, rename, delete, add security keysComponents.WebAuthn.Support- browser capability checkOverrides
Default and DaisyUI themes cover all WebAuthn components, same structure as Password and TOTP.
JS Hooks
Bundles
priv/static/webauthn_hooks.js-- handlesnavigator.credentials.create()/.get(), base64url encoding, and LiveView event bridging. Import and register the hooks in your app.js.Depends on
webauthn-strategybranch (feat: add WebAuthn/Passkey authentication strategy ash_authentication#1144)Test plan