WebauthnComponents. AuthenticationComponent
(WebauthnComponents v0.11.3)
View Source
LiveComponent for authenticating a user with a WebAuthn credential.
Use this component to sign in an existing user or to re-authenticate during sensitive operations (security changes, destructive admin actions, and so on).
Assigns
@id(Required) An HTML element ID.@mediation(Optional)"optional"(default) or"conditional".@disabled(Optional) Disables the button. Defaults tofalse.@class(Optional) CSS classes for the button.@rest(Optional) Additional HTML attributes for the button.@public_key_credential_request_options(Optional) AWebauthnComponents.PublicKeyCredentialRequestOptionsstruct controlling the request (for example,:timeout,:user_verification, and:allow_credentials).
Messages
%WebauthnComponents.FindUser{}— the user presented a credential. Reply withsend_update(WebauthnComponents.AuthenticationComponent, id: ..., credentials: credentials).{credential_id, %Wax.AuthenticatorData{}}— the credential was verified.credential_idis the raw credential id.{:error, payload}— a client-side error.payloadcontains themessage,name, andstackreported by the browser.- A
Waxerror struct (for example,%Wax.InvalidClientDataError{}) — server-side verification failed.
User Lookup
After the user approves authentication in the browser, the component sends a WebauthnComponents.FindUser.t/0 message to the parent LiveView.
The host application must locate the user, apply any relevant validation (for example, an account-status check), and send the user's credentials back with Phoenix.LiveView.send_update/3.
Each credential must expose a credential id and public key; by default the component reads the :id and :public_key fields from any struct or map.
Define an implementation of WebauthnComponents.CredentialProtocol when your schema uses different field names.
Conditional UI
Set @mediation to "conditional" to render a hidden input that lets the browser offer a Passkey while the user interacts with the page, reducing the number of steps required to sign in.
For best results, use WebauthnComponents.ClientCapabilitiesComponent to detect browser support, then update @mediation with the appropriate value.
# MyAppWeb.Authentication template
<.live_component
module={WebauthnComponents.ClientCapabilitiesComponent}
id="client-capabilities-component"
/>
<.live_component
module={WebauthnComponents.AuthenticationComponent}
id="authentication-component"
class="btn btn-primary w-full"
>
<span>Log in with a Passkey</span>
</.live_component>defmodule MyAppWeb.Authentication do
...
def handle_info({:client_capabilities, capabilities}, socket) do
if capabilities["conditionalGet"] do
send_update(WebauthnComponents.AuthenticationComponent,
id: "authentication-component",
mediation: "conditional"
)
end
{:noreply, socket}
end
endExample
defmodule MyAppWeb.Authentication do
...
def handle_info(%WebauthnComponents.FindUser{user_handle: user_handle}, socket) do
with {:ok, user} <- MyApp.Identity.get_user(user_handle),
%MyApp.Identity.User{status: :active, credentials: credentials} <- user do
send_update(WebauthnComponents.AuthenticationComponent,
id: "authentication-component",
credentials: credentials
)
{:noreply, socket}
else
error ->
Logger.warning(error)
{
:noreply,
socket
|> put_flash(:error, "Authentication failed")
}
end
end
def handle_info({_credential_id, %Wax.AuthenticatorData{}}, socket) do
# Authentication succeeded. Sign the user in.
{:noreply, socket}
end
endIn the template, render the component:
<.live_component
id="authentication-component"
module={WebauthnComponents.AuthenticationComponent}
class="btn"
>
Sign in with a Passkey
</.live_component>Resources
Summary
Functions
Callback implementation for Phoenix.LiveComponent.handle_event/3.
Callback implementation for Phoenix.LiveComponent.mount/1.
Callback implementation for Phoenix.LiveComponent.render/1.
Callback implementation for Phoenix.LiveComponent.update/2.
Functions
Callback implementation for Phoenix.LiveComponent.handle_event/3.
Callback implementation for Phoenix.LiveComponent.mount/1.
Callback implementation for Phoenix.LiveComponent.render/1.
Callback implementation for Phoenix.LiveComponent.update/2.