Skip to content

Commit

Permalink
passkey auto-upgrade need to skip user presence & verification check (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
nov authored Oct 14, 2024
1 parent f030a78 commit f683080
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 7 deletions.
2 changes: 1 addition & 1 deletion lib/webauthn/authenticator_attestation_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def initialize(attestation_object:, transports: [], **options)
@relying_party = relying_party
end

def verify(expected_challenge, expected_origin = nil, user_verification: nil, rp_id: nil)
def verify(expected_challenge, expected_origin = nil, user_presence: true, user_verification: nil, rp_id: nil)
super

verify_item(:attested_credential)
Expand Down
4 changes: 2 additions & 2 deletions lib/webauthn/authenticator_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def initialize(client_data_json:, relying_party: WebAuthn.configuration.relying_
@relying_party = relying_party
end

def verify(expected_challenge, expected_origin = nil, user_verification: nil, rp_id: nil)
def verify(expected_challenge, expected_origin = nil, user_presence: true, user_verification: nil, rp_id: nil)
expected_origin ||= relying_party.origin || raise("Unspecified expected origin")
rp_id ||= relying_party.id

Expand All @@ -35,7 +35,7 @@ def verify(expected_challenge, expected_origin = nil, user_verification: nil, rp
verify_item(:authenticator_data)
verify_item(:rp_id, rp_id || rp_id_from_origin(expected_origin))

if !relying_party.silent_authentication
if !relying_party.silent_authentication && user_presence
verify_item(:user_presence)
end

Expand Down
4 changes: 2 additions & 2 deletions lib/webauthn/public_key_credential_with_attestation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ def self.response_class
WebAuthn::AuthenticatorAttestationResponse
end

def verify(challenge, user_verification: nil)
def verify(challenge, user_presence: true, user_verification: nil)
super

response.verify(encoder.decode(challenge), user_verification: user_verification)
response.verify(encoder.decode(challenge), user_presence: user_presence, user_verification: user_verification)

true
end
Expand Down
4 changes: 2 additions & 2 deletions lib/webauthn/relying_party.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ def options_for_registration(**keyword_arguments)
)
end

def verify_registration(raw_credential, challenge, user_verification: nil)
def verify_registration(raw_credential, challenge, user_presence: true, user_verification: nil)
webauthn_credential = WebAuthn::Credential.from_create(raw_credential, relying_party: self)

if webauthn_credential.verify(challenge, user_verification: user_verification)
if webauthn_credential.verify(challenge, user_presence: user_presence, user_verification: user_verification)
webauthn_credential
end
end
Expand Down
16 changes: 16 additions & 0 deletions spec/webauthn/authenticator_attestation_response_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,22 @@
end
end

describe "user presence" do
context "when UP is not set" do
let(:public_key_credential) { client.create(challenge: original_challenge, user_present: false) }

it "verifies if user presence is not required" do
expect(attestation_response.verify(original_challenge, origin, user_presence: false)).to be_truthy
end

it "doesn't verify if user presence is required" do
expect {
attestation_response.verify(original_challenge, origin, user_presence: true)
}.to raise_exception(WebAuthn::UserPresenceVerificationError)
end
end
end

describe "user verification" do
context "when UV is not set" do
let(:public_key_credential) { client.create(challenge: original_challenge, user_verified: false) }
Expand Down
39 changes: 39 additions & 0 deletions spec/webauthn/relying_party_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,45 @@
OpenStruct.new(id: WebAuthn.generate_user_id, name: 'John Doe', credentials: [])
end

describe '#verify_registration' do
let(:options) do
admin_rp.options_for_registration(
user: user.to_h.slice(:id, :name),
exclude: user.credentials
)
end
let(:raw_credential) do
admin_fake_client.create(challenge: options.challenge, rp_id: admin_rp.id)
end

it 'require user_presence by default' do
expect_any_instance_of(WebAuthn::PublicKeyCredentialWithAttestation).to receive(:verify).with(
options.challenge,
user_presence: true,
user_verification: nil
)
admin_rp.verify_registration(raw_credential, options.challenge)
end

it 'can skip user_presence' do
expect_any_instance_of(WebAuthn::PublicKeyCredentialWithAttestation).to receive(:verify).with(
options.challenge,
user_presence: false,
user_verification: nil
)
admin_rp.verify_registration(raw_credential, options.challenge, user_presence: false)
end

it 'can require user_verification' do
expect_any_instance_of(WebAuthn::PublicKeyCredentialWithAttestation).to receive(:verify).with(
options.challenge,
user_presence: true,
user_verification: true
)
admin_rp.verify_registration(raw_credential, options.challenge, user_verification: true)
end
end

context "without having any global configuration" do
let(:consumer_rp) do
WebAuthn::RelyingParty.new(
Expand Down

0 comments on commit f683080

Please sign in to comment.