Rename request options to authentication options
This commit is contained in:
@@ -6,7 +6,7 @@ class Sessions::PasskeysController < ApplicationController
|
|||||||
rate_limit to: 10, within: 3.minutes, only: :create, with: :rate_limit_exceeded
|
rate_limit to: 10, within: 3.minutes, only: :create, with: :rate_limit_exceeded
|
||||||
|
|
||||||
def create
|
def create
|
||||||
if credential = ActionPack::Passkey.authenticate(passkey_request_params)
|
if credential = ActionPack::Passkey.authenticate(passkey_authentication_params)
|
||||||
start_new_session_for credential.holder
|
start_new_session_for credential.holder
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class SessionsController < ApplicationController
|
|||||||
layout "public"
|
layout "public"
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@request_options = passkey_request_options
|
@authentication_options = passkey_authentication_options
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= passkey_sign_in_button "Sign in with a passkey", session_passkey_path, options: @request_options, mediation: "conditional", class: "btn btn--link center txt-medium", hidden: true %>
|
<%= passkey_sign_in_button "Sign in with a passkey", session_passkey_path, options: @authentication_options, mediation: "conditional", class: "btn btn--link center txt-medium", hidden: true %>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
# Generate options for the browser's +navigator.credentials.get()+ call, then authenticate the
|
# Generate options for the browser's +navigator.credentials.get()+ call, then authenticate the
|
||||||
# response:
|
# response:
|
||||||
#
|
#
|
||||||
# options = ActionPack::Passkey.request_options
|
# options = ActionPack::Passkey.authentication_options
|
||||||
# # Pass options to the browser
|
# # Pass options to the browser
|
||||||
#
|
#
|
||||||
# passkey = ActionPack::Passkey.authenticate(params[:passkey])
|
# passkey = ActionPack::Passkey.authenticate(params[:passkey])
|
||||||
@@ -62,10 +62,10 @@ class ActionPack::Passkey < Rails.configuration.action_pack.passkey.parent_class
|
|||||||
# +navigator.credentials.get()+ call. When a +holder+ is provided, their existing credentials
|
# +navigator.credentials.get()+ call. When a +holder+ is provided, their existing credentials
|
||||||
# are included so the browser can offer them for selection. Merges global defaults, holder
|
# are included so the browser can offer them for selection. Merges global defaults, holder
|
||||||
# options, and any additional +options+ overrides.
|
# options, and any additional +options+ overrides.
|
||||||
def request_options(holder: nil, **options)
|
def authentication_options(holder: nil, **options)
|
||||||
ActionPack::WebAuthn::PublicKeyCredential.request_options(
|
ActionPack::WebAuthn::PublicKeyCredential.request_options(
|
||||||
**Rails.configuration.action_pack.web_authn.default_request_options.to_h,
|
**Rails.configuration.action_pack.web_authn.default_request_options.to_h,
|
||||||
**holder&.passkey_request_options.to_h,
|
**holder&.passkey_authentication_options.to_h,
|
||||||
**options
|
**options
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
# model that supply holder-specific options for the WebAuthn ceremonies:
|
# model that supply holder-specific options for the WebAuthn ceremonies:
|
||||||
#
|
#
|
||||||
# - +passkey_registration_options+ — merged into ActionPack::Passkey.registration_options
|
# - +passkey_registration_options+ — merged into ActionPack::Passkey.registration_options
|
||||||
# - +passkey_request_options+ — merged into ActionPack::Passkey.request_options
|
# - +passkey_authentication_options+ — merged into ActionPack::Passkey.authentication_options
|
||||||
#
|
#
|
||||||
# == Options
|
# == Options
|
||||||
#
|
#
|
||||||
@@ -32,14 +32,14 @@
|
|||||||
#
|
#
|
||||||
# has_passkeys do |config|
|
# has_passkeys do |config|
|
||||||
# config.registration_options { { name: email, display_name: name } }
|
# config.registration_options { { name: email, display_name: name } }
|
||||||
# config.request_options { { user_verification: "required" } }
|
# config.authentication_options { { user_verification: "required" } }
|
||||||
# end
|
# end
|
||||||
module ActionPack::Passkey::Holder
|
module ActionPack::Passkey::Holder
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
class_methods do
|
class_methods do
|
||||||
# Declares that this model can hold passkeys. Sets up a polymorphic +has_many+ association
|
# Declares that this model can hold passkeys. Sets up a polymorphic +has_many+ association
|
||||||
# and defines +passkey_registration_options+ and +passkey_request_options+ instance methods used
|
# and defines +passkey_registration_options+ and +passkey_authentication_options+ instance methods used
|
||||||
# by ActionPack::Passkey to build ceremony options.
|
# by ActionPack::Passkey to build ceremony options.
|
||||||
#
|
#
|
||||||
# Keyword arguments matching CreationOptions or RequestOptions fields are extracted and
|
# Keyword arguments matching CreationOptions or RequestOptions fields are extracted and
|
||||||
@@ -61,8 +61,8 @@ module ActionPack::Passkey::Holder
|
|||||||
}.merge(config.evaluate_registration_options(self))
|
}.merge(config.evaluate_registration_options(self))
|
||||||
end
|
end
|
||||||
|
|
||||||
define_method(:passkey_request_options) do
|
define_method(:passkey_authentication_options) do
|
||||||
{ credentials: public_send(config.association_name) }.merge(config.evaluate_request_options(self))
|
{ credentials: public_send(config.association_name) }.merge(config.evaluate_authentication_options(self))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -81,15 +81,15 @@ module ActionPack::Passkey::Holder
|
|||||||
end
|
end
|
||||||
|
|
||||||
if request_opts = extract_options_for(ActionPack::WebAuthn::PublicKeyCredential::RequestOptions, options)
|
if request_opts = extract_options_for(ActionPack::WebAuthn::PublicKeyCredential::RequestOptions, options)
|
||||||
@request_options = options_to_proc(request_opts)
|
@authentication_options = options_to_proc(request_opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Sets a block to evaluate in the holder's context to produce additional request options.
|
# Sets a block to evaluate in the holder's context to produce additional authentication options.
|
||||||
#
|
#
|
||||||
# config.request_options { { user_verification: "required" } }
|
# config.authentication_options { { user_verification: "required" } }
|
||||||
def request_options(&block)
|
def authentication_options(&block)
|
||||||
@request_options = block
|
@authentication_options = block
|
||||||
end
|
end
|
||||||
|
|
||||||
# Sets a block to evaluate in the holder's context to produce additional creation options.
|
# Sets a block to evaluate in the holder's context to produce additional creation options.
|
||||||
@@ -100,10 +100,10 @@ module ActionPack::Passkey::Holder
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Evaluates the request options block (if any) in the context of the given +record+. Called
|
# Evaluates the request options block (if any) in the context of the given +record+. Called
|
||||||
# internally by the +passkey_request_options+ method defined on the holder.
|
# internally by the +passkey_authentication_options+ method defined on the holder.
|
||||||
def evaluate_request_options(record)
|
def evaluate_authentication_options(record)
|
||||||
if @request_options
|
if @authentication_options
|
||||||
record.instance_exec(&@request_options)
|
record.instance_exec(&@authentication_options)
|
||||||
else
|
else
|
||||||
{}
|
{}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -27,11 +27,11 @@
|
|||||||
# include ActionPack::Passkey::Request
|
# include ActionPack::Passkey::Request
|
||||||
#
|
#
|
||||||
# def new
|
# def new
|
||||||
# @request_options = passkey_request_options
|
# @authentication_options = passkey_authentication_options
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# def create
|
# def create
|
||||||
# if passkey = ActionPack::Passkey.authenticate(passkey_request_params)
|
# if passkey = ActionPack::Passkey.authenticate(passkey_authentication_params)
|
||||||
# sign_in passkey.holder
|
# sign_in passkey.holder
|
||||||
# redirect_to root_path
|
# redirect_to root_path
|
||||||
# else
|
# else
|
||||||
@@ -61,13 +61,13 @@ module ActionPack::Passkey::Request
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Returns strong parameters for the passkey authentication ceremony.
|
# Returns strong parameters for the passkey authentication ceremony.
|
||||||
def passkey_request_params(param: :passkey)
|
def passkey_authentication_params(param: :passkey)
|
||||||
params.expect(param => [ :id, :client_data_json, :authenticator_data, :signature ])
|
params.expect(param => [ :id, :client_data_json, :authenticator_data, :signature ])
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns RequestOptions for the authentication ceremony.
|
# Returns RequestOptions for the authentication ceremony.
|
||||||
def passkey_request_options(**options)
|
def passkey_authentication_options(**options)
|
||||||
ActionPack::Passkey.request_options(**options)
|
ActionPack::Passkey.authentication_options(**options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns RegistrationOptions for the registration ceremony.
|
# Returns RegistrationOptions for the registration ceremony.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class ActionPack::PasskeyTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "authenticate with valid assertion" do
|
test "authenticate with valid assertion" do
|
||||||
challenge = ActionPack::Passkey.request_options(credentials: [ @passkey ]).challenge
|
challenge = ActionPack::Passkey.authentication_options(credentials: [ @passkey ]).challenge
|
||||||
assertion = build_assertion(challenge: challenge)
|
assertion = build_assertion(challenge: challenge)
|
||||||
|
|
||||||
result = @passkey.authenticate(assertion)
|
result = @passkey.authenticate(assertion)
|
||||||
@@ -26,7 +26,7 @@ class ActionPack::PasskeyTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "authenticate returns nil with invalid signature" do
|
test "authenticate returns nil with invalid signature" do
|
||||||
challenge = ActionPack::Passkey.request_options(credentials: [ @passkey ]).challenge
|
challenge = ActionPack::Passkey.authentication_options(credentials: [ @passkey ]).challenge
|
||||||
assertion = build_assertion(challenge: challenge)
|
assertion = build_assertion(challenge: challenge)
|
||||||
assertion[:signature] = Base64.urlsafe_encode64("invalid", padding: false)
|
assertion[:signature] = Base64.urlsafe_encode64("invalid", padding: false)
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ class ActionPack::PasskeyTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "authenticate updates sign count and backed_up" do
|
test "authenticate updates sign count and backed_up" do
|
||||||
challenge = ActionPack::Passkey.request_options(credentials: [ @passkey ]).challenge
|
challenge = ActionPack::Passkey.authentication_options(credentials: [ @passkey ]).challenge
|
||||||
assertion = build_assertion(challenge: challenge, sign_count: 5, backed_up: true)
|
assertion = build_assertion(challenge: challenge, sign_count: 5, backed_up: true)
|
||||||
|
|
||||||
@passkey.authenticate(assertion)
|
@passkey.authenticate(assertion)
|
||||||
|
|||||||
Reference in New Issue
Block a user