diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index f7c564d..2555d0d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -19,12 +19,4 @@ def current_user User.find_by(id: session[:user_id]) end end - - def relying_party - @relying_party ||= - WebAuthn::RelyingParty.new( - origin: Rails.configuration.webauthn_origin, - name: "WebAuthn Rails Demo App" - ) - end end diff --git a/app/controllers/credentials_controller.rb b/app/controllers/credentials_controller.rb index 16a95e3..07698a4 100644 --- a/app/controllers/credentials_controller.rb +++ b/app/controllers/credentials_controller.rb @@ -2,7 +2,7 @@ class CredentialsController < ApplicationController def create - create_options = relying_party.options_for_registration( + create_options = WebAuthn::Credential.options_for_create( user: { id: current_user.webauthn_id, name: current_user.username, @@ -19,29 +19,29 @@ def create end def callback - webauthn_credential = relying_party.verify_registration( - params, - session[:current_registration]["challenge"], - user_verification: true, - ) - - credential = current_user.credentials.find_or_initialize_by( - external_id: Base64.strict_encode64(webauthn_credential.raw_id) - ) - - if credential.update( - nickname: params[:credential_nickname], - public_key: webauthn_credential.public_key, - sign_count: webauthn_credential.sign_count - ) - render json: { status: "ok" }, status: :ok - else - render json: "Couldn't add your Security Key", status: :unprocessable_entity + webauthn_credential = WebAuthn::Credential.from_create(params) + + begin + webauthn_credential.verify(session[:current_registration]["challenge"], user_verification: true) + + credential = current_user.credentials.find_or_initialize_by( + external_id: Base64.strict_encode64(webauthn_credential.raw_id) + ) + + if credential.update( + nickname: params[:credential_nickname], + public_key: webauthn_credential.public_key, + sign_count: webauthn_credential.sign_count + ) + render json: { status: "ok" }, status: :ok + else + render json: "Couldn't add your Security Key", status: :unprocessable_entity + end + rescue WebAuthn::Error => e + render json: "Verification failed: #{e.message}", status: :unprocessable_entity + ensure + session.delete(:current_registration) end - rescue WebAuthn::Error => e - render json: "Verification failed: #{e.message}", status: :unprocessable_entity - ensure - session.delete(:current_registration) end def destroy diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 4e95fa6..78e491d 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -7,7 +7,7 @@ def new def create user = User.new(username: params[:registration][:username]) - create_options = relying_party.options_for_registration( + create_options = WebAuthn::Credential.options_for_create( user: { name: params[:registration][:username], id: user.webauthn_id @@ -29,14 +29,12 @@ def create end def callback + webauthn_credential = WebAuthn::Credential.from_create(params) + user = User.create!(session[:current_registration]["user_attributes"]) begin - webauthn_credential = relying_party.verify_registration( - params, - session[:current_registration]["challenge"], - user_verification: true, - ) + webauthn_credential.verify(session[:current_registration]["challenge"], user_verification: true) credential = user.credentials.build( external_id: Base64.strict_encode64(webauthn_credential.raw_id), diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 8ecc458..69b9ef9 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -8,7 +8,7 @@ def create user = User.find_by(username: session_params[:username]) if user - get_options = relying_party.options_for_authentication( + get_options = WebAuthn::Credential.options_for_get( allow: user.credentials.pluck(:external_id), user_verification: "required" ) @@ -26,19 +26,22 @@ def create end def callback + webauthn_credential = WebAuthn::Credential.from_get(params) + user = User.find_by(username: session[:current_authentication]["username"]) raise "user #{session[:current_authentication]["username"]} never initiated sign up" unless user + credential = user.credentials.find_by(external_id: Base64.strict_encode64(webauthn_credential.raw_id)) + begin - verified_webauthn_credential, stored_credential = relying_party.verify_authentication( - params, + webauthn_credential.verify( session[:current_authentication]["challenge"], + public_key: credential.public_key, + sign_count: credential.sign_count, user_verification: true, - ) do |webauthn_credential| - user.credentials.find_by(external_id: Base64.strict_encode64(webauthn_credential.raw_id)) - end + ) - stored_credential.update!(sign_count: verified_webauthn_credential.sign_count) + credential.update!(sign_count: webauthn_credential.sign_count) sign_in(user) render json: { status: "ok" }, status: :ok diff --git a/config/initializers/webauthn.rb b/config/initializers/webauthn.rb new file mode 100644 index 0000000..3d18262 --- /dev/null +++ b/config/initializers/webauthn.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +WebAuthn.configure do |config| + config.origin = Rails.configuration.webauthn_origin + config.rp_name = "WebAuthn Rails Demo App" +end