webauthn 2.5.0 → 3.0.0.alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +0 -56
  3. data/.travis.yml +39 -0
  4. data/Appraisals +12 -0
  5. data/CHANGELOG.md +0 -30
  6. data/README.md +2 -3
  7. data/SECURITY.md +3 -6
  8. data/gemfiles/cose_head.gemfile +7 -0
  9. data/gemfiles/openssl_2_0.gemfile +7 -0
  10. data/gemfiles/openssl_head.gemfile +7 -0
  11. data/lib/cose/rsapkcs1_algorithm.rb +0 -7
  12. data/lib/webauthn/attestation_object.rb +9 -5
  13. data/lib/webauthn/attestation_statement/android_key.rb +4 -0
  14. data/lib/webauthn/attestation_statement/android_safetynet.rb +5 -1
  15. data/lib/webauthn/attestation_statement/base.rb +14 -17
  16. data/lib/webauthn/attestation_statement/none.rb +1 -7
  17. data/lib/webauthn/attestation_statement.rb +3 -6
  18. data/lib/webauthn/authenticator_assertion_response.rb +4 -3
  19. data/lib/webauthn/authenticator_attestation_response.rb +10 -7
  20. data/lib/webauthn/authenticator_data/attested_credential_data.rb +10 -4
  21. data/lib/webauthn/authenticator_response.rb +6 -5
  22. data/lib/webauthn/configuration.rb +36 -38
  23. data/lib/webauthn/credential.rb +5 -4
  24. data/lib/webauthn/credential_creation_options.rb +0 -2
  25. data/lib/webauthn/credential_request_options.rb +0 -2
  26. data/lib/webauthn/fake_authenticator.rb +2 -10
  27. data/lib/webauthn/fake_client.rb +5 -12
  28. data/lib/webauthn/public_key_credential/creation_options.rb +3 -3
  29. data/lib/webauthn/public_key_credential/entity.rb +4 -3
  30. data/lib/webauthn/public_key_credential/options.rb +6 -9
  31. data/lib/webauthn/public_key_credential/request_options.rb +1 -1
  32. data/lib/webauthn/public_key_credential.rb +15 -8
  33. data/lib/webauthn/relying_party.rb +117 -0
  34. data/lib/webauthn/version.rb +1 -1
  35. data/script/ci/install-openssl +7 -0
  36. data/script/ci/install-ruby +13 -0
  37. data/webauthn.gemspec +6 -7
  38. metadata +26 -35
  39. data/.github/workflows/build.yml +0 -36
  40. data/lib/webauthn/attestation_statement/apple.rb +0 -65
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e6487b19f172c0c7e96af23d04e47f91bebd2ef7d20f144f99f85e761a2db86
4
- data.tar.gz: 7623405e7cd01708f29897a0d4183fbc8c9b2a3dfb06b9c182646ddaf9c6cb0d
3
+ metadata.gz: 1f418eb52a085d8e7c03bd1c3d11b88ed8fe467f4ec01d3178836689d470f436
4
+ data.tar.gz: 4ab67e8804cbd7d785e29b94760af6db9d6b1e52de1a58bafc74aed19b5b7e21
5
5
  SHA512:
6
- metadata.gz: d2f8d2137b2ee140a3258fbbff8d62e49264b2eafa80f0726dacc16a742addf75625b9da51696db6f3862a85e63f44ca5fc2b73320b1c256dd1c57f96121de24
7
- data.tar.gz: dcb2ea914a14944b4bf7c4682394df12e00ddd4a4b0cc1076a03a7368bf4d563d08b61fbbe27ece3ddcbc05a9ed542d8236c1bfce833669c9b60c5d3387b35b4
6
+ metadata.gz: ccdcd22e494079eb67c122c03e3061166f91de50dd0c2bf8662748c976483a9d472fa9f8d6b67db9abf484e8eac182195b5f1e1cca8aaaf88146d831919f1c93
7
+ data.tar.gz: b2506b530c796ee57e5d037e7dd3692b1e359408fd9757141b6c4f042c43d57344baa09dc63d17ace549927eeea50abaa8c0771a0ab6da0ece5d880362d890db
data/.rubocop.yml CHANGED
@@ -1,6 +1,5 @@
1
1
  require:
2
2
  - rubocop-rspec
3
- - rubocop-rake
4
3
 
5
4
  inherit_mode:
6
5
  merge:
@@ -9,7 +8,6 @@ inherit_mode:
9
8
  AllCops:
10
9
  TargetRubyVersion: 2.4
11
10
  DisabledByDefault: true
12
- NewCops: disable
13
11
  Exclude:
14
12
  - "gemfiles/**/*"
15
13
  - "vendor/**/*"
@@ -26,12 +24,6 @@ Layout:
26
24
  Layout/ClassStructure:
27
25
  Enabled: true
28
26
 
29
- Layout/EmptyLineBetweenDefs:
30
- AllowAdjacentOneLineDefs: true
31
-
32
- Layout/EmptyLinesAroundAttributeAccessor:
33
- Enabled: true
34
-
35
27
  Layout/FirstMethodArgumentLineBreak:
36
28
  Enabled: true
37
29
 
@@ -46,60 +38,12 @@ Layout/MultilineAssignmentLayout:
46
38
  Layout/MultilineMethodArgumentLineBreaks:
47
39
  Enabled: true
48
40
 
49
- Layout/SpaceAroundMethodCallOperator:
50
- Enabled: true
51
-
52
41
  Lint:
53
42
  Enabled: true
54
43
 
55
- Lint/DeprecatedOpenSSLConstant:
56
- Enabled: true
57
-
58
- Lint/MixedRegexpCaptureTypes:
59
- Enabled: true
60
-
61
- Lint/RaiseException:
62
- Enabled: true
63
-
64
- Lint/StructNewOverride:
65
- Enabled: true
66
-
67
- Lint/BinaryOperatorWithIdenticalOperands:
68
- Enabled: true
69
-
70
- Lint/DuplicateElsifCondition:
71
- Enabled: true
72
-
73
- Lint/DuplicateRescueException:
74
- Enabled: true
75
-
76
- Lint/EmptyConditionalBody:
77
- Enabled: true
78
-
79
- Lint/FloatComparison:
80
- Enabled: true
81
-
82
- Lint/MissingSuper:
83
- Enabled: true
84
-
85
- Lint/OutOfRangeRegexpRef:
86
- Enabled: true
87
-
88
- Lint/SelfAssignment:
89
- Enabled: true
90
-
91
- Lint/TopLevelReturnWithArgument:
92
- Enabled: true
93
-
94
- Lint/UnreachableLoop:
95
- Enabled: true
96
-
97
44
  Naming:
98
45
  Enabled: true
99
46
 
100
- Naming/VariableNumber:
101
- Enabled: false
102
-
103
47
  RSpec/Be:
104
48
  Enabled: true
105
49
 
data/.travis.yml ADDED
@@ -0,0 +1,39 @@
1
+ dist: bionic
2
+ language: ruby
3
+
4
+ cache:
5
+ bundler: true
6
+ directories:
7
+ - /home/travis/.rvm/
8
+
9
+ env:
10
+ - LIBSSL=1.1 RB=2.7.1
11
+ - LIBSSL=1.1 RB=2.6.6
12
+ - LIBSSL=1.1 RB=2.5.8
13
+ - LIBSSL=1.1 RB=2.4.10
14
+ - LIBSSL=1.1 RB=ruby-head
15
+ - LIBSSL=1.0 RB=2.7.1
16
+ - LIBSSL=1.0 RB=2.6.6
17
+ - LIBSSL=1.0 RB=2.5.8
18
+ - LIBSSL=1.0 RB=2.4.10
19
+ - LIBSSL=1.0 RB=ruby-head
20
+
21
+ gemfile:
22
+ - gemfiles/cose_head.gemfile
23
+ - gemfiles/openssl_head.gemfile
24
+ - gemfiles/openssl_2_2.gemfile
25
+ - gemfiles/openssl_2_1.gemfile
26
+ - gemfiles/openssl_2_0.gemfile
27
+
28
+ matrix:
29
+ fast_finish: true
30
+ allow_failures:
31
+ - env: LIBSSL=1.1 RB=ruby-head
32
+ - env: LIBSSL=1.0 RB=ruby-head
33
+ - gemfile: gemfiles/cose_head.gemfile
34
+ - gemfile: gemfiles/openssl_head.gemfile
35
+
36
+ before_install:
37
+ - ./script/ci/install-openssl
38
+ - ./script/ci/install-ruby
39
+ - gem install bundler -v "~> 2.0"
data/Appraisals CHANGED
@@ -1,5 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ appraise "cose_head" do
4
+ gem "cose", git: "https://github.com/cedarcode/cose-ruby"
5
+ end
6
+
7
+ appraise "openssl_head" do
8
+ gem "openssl", git: "https://github.com/ruby/openssl"
9
+ end
10
+
3
11
  appraise "openssl_2_2" do
4
12
  gem "openssl", "~> 2.2.0"
5
13
  end
@@ -7,3 +15,7 @@ end
7
15
  appraise "openssl_2_1" do
8
16
  gem "openssl", "~> 2.1.0"
9
17
  end
18
+
19
+ appraise "openssl_2_0" do
20
+ gem "openssl", "~> 2.0.0"
21
+ end
data/CHANGELOG.md CHANGED
@@ -6,30 +6,6 @@
6
6
 
7
7
  - Ability to define multiple relying parties with the introduction of the `WebAuthn::RelyingParty` class ([@padulafacundo], [@brauliomartinezlm])
8
8
 
9
- ## [v2.5.0] - 2021-03-14
10
-
11
- ### Added
12
-
13
- - Support 'apple' attestation statement format ([#343](https://github.com/cedarcode/webauthn-ruby/pull/343) / [@juanarias93], [@santiagorodriguez96])
14
- - Allow specifying an array of ids as `allow_credentials:` for `FakeClient#get` method ([#335](https://github.com/cedarcode/webauthn-ruby/pull/335) / [@kingjan1999])
15
-
16
- ### Removed
17
-
18
- - No longer accept "removed from the WebAuthn spec" options `rp: { icon: }` and `user: { icon: }` for `WebAuthn::Credential.options_for_create` method ([#326](https://github.com/cedarcode/webauthn-ruby/pull/326) / [@santiagorodriguez96])
19
-
20
- ## [v2.4.1] - 2021-02-15
21
-
22
- ### Fixed
23
-
24
- - Fix verification of new credential if no attestation provided and 'None' type is not among configured `acceptable_attestation_types`. I.e. reject it instead of letting it go through.
25
-
26
- ## [v2.4.0] - 2020-09-03
27
-
28
- ### Added
29
-
30
- - Support for ES256K credentials
31
- - `FakeClient#get` accepts `user_handle:` keyword argument ([@lgarron])
32
-
33
9
  ## [v2.3.0] - 2020-06-27
34
10
 
35
11
  ### Added
@@ -325,9 +301,6 @@ Note: Both additions should help making it compatible with Chrome for Android 70
325
301
  - Works with ruby 2.5
326
302
 
327
303
  [v3.0.0.alpha1]: https://github.com/cedarcode/webauthn-ruby/compare/2-stable...v3.0.0.alpha1/
328
- [v2.5.0]: https://github.com/cedarcode/webauthn-ruby/compare/v2.4.1...v2.5.0/
329
- [v2.4.1]: https://github.com/cedarcode/webauthn-ruby/compare/v2.4.0...v2.4.1/
330
- [v2.4.0]: https://github.com/cedarcode/webauthn-ruby/compare/v2.3.0...v2.4.0/
331
304
  [v2.3.0]: https://github.com/cedarcode/webauthn-ruby/compare/v2.2.1...v2.3.0/
332
305
  [v2.2.1]: https://github.com/cedarcode/webauthn-ruby/compare/v2.2.0...v2.2.1/
333
306
  [v2.2.0]: https://github.com/cedarcode/webauthn-ruby/compare/v2.1.0...v2.2.0/
@@ -364,6 +337,3 @@ Note: Both additions should help making it compatible with Chrome for Android 70
364
337
  [@ssuttner]: https://github.com/ssuttner
365
338
  [@padulafacundo]: https://github.com/padulafacundo
366
339
  [@santiagorodriguez96]: https://github.com/santiagorodriguez96
367
- [@lgarron]: https://github.com/lgarron
368
- [@juanarias93]: https://github.com/juanarias93
369
- [@kingjan1999]: https://github.com/@kingjan1999
data/README.md CHANGED
@@ -6,7 +6,7 @@ For the current release version see https://github.com/cedarcode/webauthn-ruby/b
6
6
  ![banner](assets/webauthn-ruby.png)
7
7
 
8
8
  [![Gem](https://img.shields.io/gem/v/webauthn.svg?style=flat-square)](https://rubygems.org/gems/webauthn)
9
- [![Travis](https://img.shields.io/travis/cedarcode/webauthn-ruby/master.svg?style=flat-square)](https://travis-ci.com/cedarcode/webauthn-ruby)
9
+ [![Travis](https://img.shields.io/travis/cedarcode/webauthn-ruby/master.svg?style=flat-square)](https://travis-ci.org/cedarcode/webauthn-ruby)
10
10
  [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-informational.svg?style=flat-square)](https://conventionalcommits.org)
11
11
  [![Join the chat at https://gitter.im/cedarcode/webauthn-ruby](https://badges.gitter.im/cedarcode/webauthn-ruby.svg)](https://gitter.im/cedarcode/webauthn-ruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
12
12
 
@@ -408,7 +408,7 @@ credential.authenticator_extension_outputs
408
408
 
409
409
  ## Attestation
410
410
 
411
- ### Attestation Statement Formats
411
+ ### Attestation Statement Format
412
412
 
413
413
  | Attestation Statement Format | Supported? |
414
414
  | -------- | :--------: |
@@ -417,7 +417,6 @@ credential.authenticator_extension_outputs
417
417
  | tpm (x5c attestation) | Yes |
418
418
  | android-key | Yes |
419
419
  | android-safetynet | Yes |
420
- | apple | Yes |
421
420
  | fido-u2f | Yes |
422
421
  | none | Yes |
423
422
 
data/SECURITY.md CHANGED
@@ -4,12 +4,9 @@
4
4
 
5
5
  | Version | Supported |
6
6
  | ------- | ------------------ |
7
- | 2.5.z | :white_check_mark: |
8
- | 2.4.z | :white_check_mark: |
9
- | 2.3.z | :white_check_mark: |
10
- | 2.2.z | :x: |
11
- | 2.1.z | :x: |
12
- | 2.0.z | :x: |
7
+ | 2.2.z | :white_check_mark: |
8
+ | 2.1.z | :white_check_mark: |
9
+ | 2.0.z | :white_check_mark: |
13
10
  | 1.18.z | :white_check_mark: |
14
11
  | < 1.18 | :x: |
15
12
 
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "cose", git: "https://github.com/cedarcode/cose-ruby"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "openssl", "~> 2.0.0"
6
+
7
+ gemspec path: "../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "openssl", git: "https://github.com/ruby/openssl"
6
+
7
+ gemspec path: "../"
@@ -40,11 +40,4 @@ end
40
40
  COSE::Algorithm.register(RSAPKCS1Algorithm.new(-257, "RS256", hash_function: "SHA256"))
41
41
  COSE::Algorithm.register(RSAPKCS1Algorithm.new(-258, "RS384", hash_function: "SHA384"))
42
42
  COSE::Algorithm.register(RSAPKCS1Algorithm.new(-259, "RS512", hash_function: "SHA512"))
43
-
44
- # Patch openssl-signature_algorithm gem to support discouraged/deprecated RSA-PKCS#1 with SHA-1
45
- # (RS1 in JOSE/COSE terminology) algorithm needed for WebAuthn.
46
- OpenSSL::SignatureAlgorithm::RSAPKCS1.const_set(
47
- :ACCEPTED_HASH_FUNCTIONS,
48
- OpenSSL::SignatureAlgorithm::RSAPKCS1::ACCEPTED_HASH_FUNCTIONS + ["SHA1"]
49
- )
50
43
  COSE::Algorithm.register(RSAPKCS1Algorithm.new(-65535, "RS1", hash_function: "SHA1"))
@@ -10,18 +10,22 @@ module WebAuthn
10
10
  class AttestationObject
11
11
  extend Forwardable
12
12
 
13
- def self.deserialize(attestation_object)
14
- from_map(CBOR.decode(attestation_object))
13
+ def self.deserialize(attestation_object, relying_party)
14
+ from_map(CBOR.decode(attestation_object), relying_party)
15
15
  end
16
16
 
17
- def self.from_map(map)
17
+ def self.from_map(map, relying_party)
18
18
  new(
19
19
  authenticator_data: WebAuthn::AuthenticatorData.deserialize(map["authData"]),
20
- attestation_statement: WebAuthn::AttestationStatement.from(map["fmt"], map["attStmt"])
20
+ attestation_statement: WebAuthn::AttestationStatement.from(
21
+ map["fmt"],
22
+ map["attStmt"],
23
+ relying_party: relying_party
24
+ )
21
25
  )
22
26
  end
23
27
 
24
- attr_reader :authenticator_data, :attestation_statement
28
+ attr_reader :authenticator_data, :attestation_statement, :relying_party
25
29
 
26
30
  def initialize(authenticator_data:, attestation_statement:)
27
31
  @authenticator_data = authenticator_data
@@ -20,6 +20,10 @@ module WebAuthn
20
20
 
21
21
  private
22
22
 
23
+ def matching_public_key?(authenticator_data)
24
+ attestation_certificate.public_key.to_der == authenticator_data.credential.public_key_object.to_der
25
+ end
26
+
23
27
  def valid_attestation_challenge?(client_data_hash)
24
28
  android_key_attestation.verify_challenge(client_data_hash)
25
29
  rescue AndroidKeyAttestation::ChallengeMismatchError
@@ -16,6 +16,10 @@ module WebAuthn
16
16
  [attestation_type, attestation_trust_path]
17
17
  end
18
18
 
19
+ def attestation_certificate
20
+ attestation_trust_path.first
21
+ end
22
+
19
23
  private
20
24
 
21
25
  def valid_response?(authenticator_data, client_data_hash)
@@ -48,7 +52,7 @@ module WebAuthn
48
52
  end
49
53
 
50
54
  # SafetyNetAttestation returns full chain including root, WebAuthn expects only the x5c certificates
51
- def certificates
55
+ def attestation_trust_path
52
56
  attestation_response.certificate_chain[0..-2]
53
57
  end
54
58
 
@@ -16,20 +16,19 @@ module WebAuthn
16
16
  ATTESTATION_TYPE_SELF = "Self"
17
17
  ATTESTATION_TYPE_ATTCA = "AttCA"
18
18
  ATTESTATION_TYPE_BASIC_OR_ATTCA = "Basic_or_AttCA"
19
- ATTESTATION_TYPE_ANONCA = "AnonCA"
20
19
 
21
20
  ATTESTATION_TYPES_WITH_ROOT = [
22
21
  ATTESTATION_TYPE_BASIC,
23
22
  ATTESTATION_TYPE_BASIC_OR_ATTCA,
24
- ATTESTATION_TYPE_ATTCA,
25
- ATTESTATION_TYPE_ANONCA
23
+ ATTESTATION_TYPE_ATTCA
26
24
  ].freeze
27
25
 
28
26
  class Base
29
27
  AAGUID_EXTENSION_OID = "1.3.6.1.4.1.45724.1.1.4"
30
28
 
31
- def initialize(statement)
29
+ def initialize(statement, relying_party = WebAuthn.configuration.relying_party)
32
30
  @statement = statement
31
+ @relying_party = relying_party
33
32
  end
34
33
 
35
34
  def valid?(_authenticator_data, _client_data_hash)
@@ -44,13 +43,19 @@ module WebAuthn
44
43
  certificates&.first
45
44
  end
46
45
 
46
+ def certificate_chain
47
+ if certificates
48
+ certificates[1..-1]
49
+ end
50
+ end
51
+
47
52
  def attestation_certificate_key_id
48
53
  raw_subject_key_identifier&.unpack("H*")&.[](0)
49
54
  end
50
55
 
51
56
  private
52
57
 
53
- attr_reader :statement
58
+ attr_reader :statement, :relying_party
54
59
 
55
60
  def matching_aaguid?(attested_credential_data_aaguid)
56
61
  extension = attestation_certificate&.extensions&.detect { |ext| ext.oid == AAGUID_EXTENSION_OID }
@@ -64,10 +69,6 @@ module WebAuthn
64
69
  end
65
70
  end
66
71
 
67
- def matching_public_key?(authenticator_data)
68
- attestation_certificate.public_key.to_der == authenticator_data.credential.public_key_object.to_der
69
- end
70
-
71
72
  def certificates
72
73
  @certificates ||=
73
74
  raw_certificates&.map do |raw_certificate|
@@ -95,10 +96,10 @@ module WebAuthn
95
96
 
96
97
  def trustworthy?(aaguid: nil, attestation_certificate_key_id: nil)
97
98
  if ATTESTATION_TYPES_WITH_ROOT.include?(attestation_type)
98
- configuration.acceptable_attestation_types.include?(attestation_type) &&
99
+ relying_party.acceptable_attestation_types.include?(attestation_type) &&
99
100
  valid_certificate_chain?(aaguid: aaguid, attestation_certificate_key_id: attestation_certificate_key_id)
100
101
  else
101
- configuration.acceptable_attestation_types.include?(attestation_type)
102
+ relying_party.acceptable_attestation_types.include?(attestation_type)
102
103
  end
103
104
  end
104
105
 
@@ -122,7 +123,7 @@ module WebAuthn
122
123
 
123
124
  def root_certificates(aaguid: nil, attestation_certificate_key_id: nil)
124
125
  root_certificates =
125
- configuration.attestation_root_certificates_finders.reduce([]) do |certs, finder|
126
+ relying_party.attestation_root_certificates_finders.reduce([]) do |certs, finder|
126
127
  if certs.empty?
127
128
  finder.find(
128
129
  attestation_format: format,
@@ -169,14 +170,10 @@ module WebAuthn
169
170
  def cose_algorithm
170
171
  @cose_algorithm ||=
171
172
  COSE::Algorithm.find(algorithm).tap do |alg|
172
- alg && configuration.algorithms.include?(alg.name) ||
173
+ alg && relying_party.algorithms.include?(alg.name) ||
173
174
  raise(UnsupportedAlgorithm, "Unsupported algorithm #{algorithm}")
174
175
  end
175
176
  end
176
-
177
- def configuration
178
- WebAuthn.configuration
179
- end
180
177
  end
181
178
  end
182
179
  end