Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
- Add support for crossOrigin/topOrigin verification during credential registration and authentication. [#486](https://github.com/cedarcode/webauthn-ruby/pull/486) [@nicolastemciuc]
- Add support for the `attestation_formats` option in `WebAuthn::Credential.options_for_create`. [#514](https://github.com/cedarcode/webauthn-ruby/pull/514) [@santiagorodriguez96]
- Add support for the `hints` option in `WebAuthn::Credential.options_for_create` and `WebAuthn::Credential.options_for_get`. [#513](https://github.com/cedarcode/webauthn-ruby/pull/513) [@santiagorodriguez96]
- Reject authenticator data where the BS (backup state) flag is set but the BE (backup eligibility) flag is not, during credential registration and authentication. Raises `WebAuthn::BackupFlagsVerificationError`. [#516](https://github.com/cedarcode/webauthn-ruby/pull/516) [@santiagorodriguez96]

### Changed

- Bump the default `credential_options_timeout` from `120_000` to `300_000` milliseconds (5 minutes). [#515](https://github.com/cedarcode/webauthn-ruby/pull/515) [@santiagorodriguez96]
- `WebAuthn::FakeClient#get` now defaults `backup_state` to `false`. The previous default (`backup_eligibility: false`, `backup_state: true`) produced authenticator data that now fails verification. [#516](https://github.com/cedarcode/webauthn-ruby/pull/516) [@santiagorodriguez96]

### Removed

Expand Down
7 changes: 7 additions & 0 deletions lib/webauthn/authenticator_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module WebAuthn
class VerificationError < Error; end

class AuthenticatorDataVerificationError < VerificationError; end
class BackupFlagsVerificationError < VerificationError; end
class ChallengeVerificationError < VerificationError; end
class OriginVerificationError < VerificationError; end
class RpIdVerificationError < VerificationError; end
Expand Down Expand Up @@ -49,6 +50,8 @@ def verify(expected_challenge, expected_origin = nil, user_presence: nil, user_v
verify_item(:user_verified)
end

verify_item(:backup_flags)

true
end

Expand Down Expand Up @@ -116,6 +119,10 @@ def valid_user_verified?
authenticator_data.user_verified?
end

def valid_backup_flags?
authenticator_data.credential_backup_eligible? || !authenticator_data.credential_backed_up?
end

def rp_id_from_origin(expected_origin)
URI.parse(expected_origin.first).host if expected_origin.size == 1
end
Expand Down
2 changes: 1 addition & 1 deletion lib/webauthn/fake_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def get(challenge: fake_challenge,
user_present: true,
user_verified: false,
backup_eligibility: false,
backup_state: true,
backup_state: false,
sign_count: nil,
extensions: nil,
user_handle: nil,
Expand Down
34 changes: 34 additions & 0 deletions spec/webauthn/authenticator_assertion_response_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,40 @@
end
end

describe "backup flags validation" do
let(:assertion) do
client.get(challenge: original_challenge, backup_eligibility: backup_eligibility, backup_state: backup_state)
end

context "when the credential is backup eligible and backed up" do
let(:backup_eligibility) { true }
let(:backup_state) { true }

it_behaves_like "a valid assertion response"
end

context "when the credential is backup eligible and not backed up" do
let(:backup_eligibility) { true }
let(:backup_state) { false }

it_behaves_like "a valid assertion response"
end

context "when the credential is not backup eligible and not backed up" do
let(:backup_eligibility) { false }
let(:backup_state) { false }

it_behaves_like "a valid assertion response"
end

context "when the credential is not backup eligible but backed up" do
let(:backup_eligibility) { false }
let(:backup_state) { true }

it_behaves_like "an invalid assertion response that raises", WebAuthn::BackupFlagsVerificationError
end
end

describe "challenge validation" do
context "if challenge doesn't match" do
let(:challenge) { fake_challenge }
Expand Down
38 changes: 38 additions & 0 deletions spec/webauthn/authenticator_attestation_response_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,44 @@
end
end

describe "backup flags validation" do
let(:public_key_credential) do
client.create(challenge: original_challenge, backup_eligibility: backup_eligibility, backup_state: backup_state)
end

before do
WebAuthn.configuration.allowed_origins = [origin]
end

context "when the credential is backup eligible and backed up" do
let(:backup_eligibility) { true }
let(:backup_state) { true }

it_behaves_like "a valid attestation response"
end

context "when the credential is backup eligible and not backed up" do
let(:backup_eligibility) { true }
let(:backup_state) { false }

it_behaves_like "a valid attestation response"
end

context "when the credential is not backup eligible and not backed up" do
let(:backup_eligibility) { false }
let(:backup_state) { false }

it_behaves_like "a valid attestation response"
end

context "when the credential is not backup eligible but backed up" do
let(:backup_eligibility) { false }
let(:backup_state) { true }

it_behaves_like "an invalid attestation response that raises", WebAuthn::BackupFlagsVerificationError
end
end

describe "rp_id validation" do
let(:original_challenge) { fake_challenge }

Expand Down
Loading