mirror of
https://github.com/System-End/identity-vault.git
synced 2026-04-19 22:05:07 +00:00
73 lines
2.4 KiB
Ruby
73 lines
2.4 KiB
Ruby
class IdentityWebauthnCredentialsController < ApplicationController
|
|
include WebauthnAuthenticatable
|
|
|
|
def index
|
|
@webauthn_credentials = current_identity.webauthn_credentials.order(created_at: :desc)
|
|
render layout: request.headers["HX-Request"] ? "htmx" : false
|
|
end
|
|
|
|
def new
|
|
render layout: request.headers["HX-Request"] ? "htmx" : false
|
|
end
|
|
|
|
def options
|
|
challenge = WebAuthn::Credential.options_for_create(
|
|
user: {
|
|
id: current_identity.webauthn_user_id,
|
|
name: current_identity.primary_email,
|
|
display_name: "#{current_identity.first_name} #{current_identity.last_name}"
|
|
},
|
|
exclude: current_identity.webauthn_credentials.raw_credential_ids,
|
|
authenticator_selection: {
|
|
user_verification: "required",
|
|
resident_key: "preferred"
|
|
}
|
|
)
|
|
|
|
session[:webauthn_registration_challenge] = challenge.challenge
|
|
|
|
render json: challenge
|
|
end
|
|
|
|
def create
|
|
# Delete challenge immediately to prevent replay attacks (single-use)
|
|
stored_challenge = session.delete(:webauthn_registration_challenge)
|
|
|
|
unless stored_challenge.present?
|
|
flash[:error] = "Registration session expired. Please try again."
|
|
redirect_to security_path and return
|
|
end
|
|
|
|
begin
|
|
credential_data = JSON.parse(params[:credential_data])
|
|
nickname = params[:nickname]
|
|
|
|
webauthn_credential = WebAuthn::Credential.from_create(credential_data)
|
|
|
|
webauthn_credential.verify(stored_challenge)
|
|
|
|
credential = current_identity.webauthn_credentials.create!(
|
|
webauthn_id: webauthn_credential.id,
|
|
webauthn_public_key: webauthn_credential.public_key,
|
|
nickname: nickname.presence,
|
|
sign_count: webauthn_credential.sign_count
|
|
)
|
|
|
|
flash[:success] = t(".successfully_added")
|
|
redirect_to security_path
|
|
rescue WebAuthn::Error => e
|
|
Rails.logger.error "WebAuthn registration error: credential creation failed"
|
|
flash[:error] = "Passkey registration failed. Please try again."
|
|
render :new, status: :unprocessable_entity
|
|
rescue => e
|
|
Rails.logger.error "Unexpected WebAuthn registration error: #{e.class.name}"
|
|
flash[:error] = "An unexpected error occurred. Please try again."
|
|
render :new, status: :unprocessable_entity
|
|
end
|
|
end
|
|
|
|
def destroy
|
|
session[:pending_destroy_credential_id] = params[:id]
|
|
redirect_to new_step_up_path(action_type: "remove_passkey")
|
|
end
|
|
end
|