Auto-suggest name for new Passkeys

- Use plain client data json everywhere
- Expose AAGUID and backed_up on Credentials
- Make attestation verifiers configurable
- Auto-suggest names for passkeys and show icons
This commit is contained in:
Stanko K.R.
2026-02-19 10:56:22 +01:00
parent b23660d897
commit fbe9252db1
53 changed files with 666 additions and 172 deletions
@@ -10,6 +10,7 @@ module CurrentRequest
Current.referrer = request.referrer
ActionPack::WebAuthn::Current.host = request.host
ActionPack::WebAuthn::Current.origin = request.base_url
end
end
end
@@ -5,12 +5,8 @@ class Sessions::PasskeysController < ApplicationController
def create
credential = Identity::Credential.authenticate(
id: params.expect(:credential_id),
client_data_json: response_params[:client_data_json],
authenticator_data: response_params[:authenticator_data],
signature: response_params[:signature],
challenge: session.delete(:webauthn_challenge),
origin: request.base_url
passkey: passkey_params,
challenge: session.delete(:webauthn_challenge)
)
if credential
@@ -21,8 +17,8 @@ class Sessions::PasskeysController < ApplicationController
end
private
def response_params
params.expect(response: [ :client_data_json, :authenticator_data, :signature ])
def passkey_params
params.expect(passkey: [ :id, :client_data_json, :authenticator_data, :signature ])
end
def authentication_succeeded(identity)
+19 -13
View File
@@ -1,26 +1,28 @@
class Users::CredentialsController < ApplicationController
before_action :set_credential, only: :destroy
before_action :set_credential, only: %i[ edit update destroy ]
def index
@credentials = Current.identity.credentials.order(name: :asc, created_at: :desc)
end
def new
@creation_options = Identity::Credential.creation_options(identity: Current.identity, display_name: Current.user.name)
session[:webauthn_challenge] = @creation_options.challenge
end
def create
Identity::Credential.register(
identity: Current.identity,
name: credential_params[:name],
client_data_json: credential_params[:client_data_json],
attestation_object: credential_params[:attestation_object],
challenge: session.delete(:webauthn_challenge),
origin: request.base_url,
transports: Array(credential_params[:transports])
credential = Current.identity.credentials.register(
passkey: passkey_params,
challenge: session.delete(:webauthn_challenge)
)
render json: { location: edit_user_credential_path(Current.user, credential, created: true) }
rescue ActionPack::WebAuthn::Authenticator::Response::InvalidResponseError => error
render json: { error: error.message }, status: :unprocessable_entity
end
def edit
end
def update
@credential.update!(credential_params)
redirect_to user_credentials_path(Current.user)
end
@@ -35,6 +37,10 @@ class Users::CredentialsController < ApplicationController
end
def credential_params
params.expect(credential: [ :name, :client_data_json, :attestation_object, transports: [] ])
params.expect(credential: [ :name ])
end
def passkey_params
params.expect(passkey: [ :client_data_json, :attestation_object, transports: [] ])
end
end