webauthn 2.5.0 → 3.0.0

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +3 -7
  3. data/.github/workflows/git.yml +21 -0
  4. data/.rubocop.yml +1 -1
  5. data/CHANGELOG.md +42 -1
  6. data/README.md +5 -3
  7. data/docs/advanced_configuration.md +174 -0
  8. data/docs/u2f_migration.md +14 -20
  9. data/lib/webauthn/attestation_object.rb +9 -5
  10. data/lib/webauthn/attestation_statement/apple.rb +2 -2
  11. data/lib/webauthn/attestation_statement/base.rb +11 -25
  12. data/lib/webauthn/attestation_statement/packed.rb +1 -1
  13. data/lib/webauthn/attestation_statement/tpm.rb +2 -2
  14. data/lib/webauthn/attestation_statement.rb +2 -2
  15. data/lib/webauthn/authenticator_assertion_response.rb +4 -3
  16. data/lib/webauthn/authenticator_attestation_response.rb +10 -7
  17. data/lib/webauthn/authenticator_data/attested_credential_data.rb +10 -5
  18. data/lib/webauthn/authenticator_data.rb +10 -2
  19. data/lib/webauthn/authenticator_response.rb +7 -7
  20. data/lib/webauthn/configuration.rb +38 -38
  21. data/lib/webauthn/credential.rb +5 -4
  22. data/lib/webauthn/fake_authenticator/attestation_object.rb +8 -0
  23. data/lib/webauthn/fake_authenticator/authenticator_data.rb +20 -5
  24. data/lib/webauthn/fake_authenticator.rb +9 -1
  25. data/lib/webauthn/fake_client.rb +10 -2
  26. data/lib/webauthn/public_key_credential/creation_options.rb +3 -3
  27. data/lib/webauthn/public_key_credential/options.rb +9 -8
  28. data/lib/webauthn/public_key_credential/request_options.rb +11 -1
  29. data/lib/webauthn/public_key_credential.rb +24 -5
  30. data/lib/webauthn/public_key_credential_with_assertion.rb +14 -1
  31. data/lib/webauthn/relying_party.rb +120 -0
  32. data/lib/webauthn/u2f_migrator.rb +4 -1
  33. data/lib/webauthn/version.rb +1 -1
  34. data/webauthn.gemspec +3 -5
  35. metadata +16 -45
  36. data/Appraisals +0 -9
  37. data/gemfiles/openssl_2_1.gemfile +0 -7
  38. data/gemfiles/openssl_2_2.gemfile +0 -7
  39. data/lib/webauthn/security_utils.rb +0 -20
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openssl"
4
+ require "webauthn/credential"
5
+ require "webauthn/encoder"
6
+ require "webauthn/error"
7
+
8
+ module WebAuthn
9
+ class RootCertificateFinderNotSupportedError < Error; end
10
+
11
+ class RelyingParty
12
+ def self.if_pss_supported(algorithm)
13
+ OpenSSL::PKey::RSA.instance_methods.include?(:verify_pss) ? algorithm : nil
14
+ end
15
+
16
+ DEFAULT_ALGORITHMS = ["ES256", "PS256", "RS256"].compact.freeze
17
+
18
+ def initialize(
19
+ algorithms: DEFAULT_ALGORITHMS.dup,
20
+ encoding: WebAuthn::Encoder::STANDARD_ENCODING,
21
+ origin: nil,
22
+ id: nil,
23
+ name: nil,
24
+ verify_attestation_statement: true,
25
+ credential_options_timeout: 120000,
26
+ silent_authentication: false,
27
+ acceptable_attestation_types: ['None', 'Self', 'Basic', 'AttCA', 'Basic_or_AttCA', 'AnonCA'],
28
+ attestation_root_certificates_finders: [],
29
+ legacy_u2f_appid: nil
30
+ )
31
+ @algorithms = algorithms
32
+ @encoding = encoding
33
+ @origin = origin
34
+ @id = id
35
+ @name = name
36
+ @verify_attestation_statement = verify_attestation_statement
37
+ @credential_options_timeout = credential_options_timeout
38
+ @silent_authentication = silent_authentication
39
+ @acceptable_attestation_types = acceptable_attestation_types
40
+ @legacy_u2f_appid = legacy_u2f_appid
41
+ self.attestation_root_certificates_finders = attestation_root_certificates_finders
42
+ end
43
+
44
+ attr_accessor :algorithms,
45
+ :encoding,
46
+ :origin,
47
+ :id,
48
+ :name,
49
+ :verify_attestation_statement,
50
+ :credential_options_timeout,
51
+ :silent_authentication,
52
+ :acceptable_attestation_types,
53
+ :legacy_u2f_appid
54
+
55
+ attr_reader :attestation_root_certificates_finders
56
+
57
+ # This is the user-data encoder.
58
+ # Used to decode user input and to encode data provided to the user.
59
+ def encoder
60
+ @encoder ||= WebAuthn::Encoder.new(encoding)
61
+ end
62
+
63
+ def attestation_root_certificates_finders=(finders)
64
+ if !finders.respond_to?(:each)
65
+ finders = [finders]
66
+ end
67
+
68
+ finders.each do |finder|
69
+ unless finder.respond_to?(:find)
70
+ raise RootCertificateFinderNotSupportedError, "Finder must implement `find` method"
71
+ end
72
+ end
73
+
74
+ @attestation_root_certificates_finders = finders
75
+ end
76
+
77
+ def options_for_registration(**keyword_arguments)
78
+ WebAuthn::Credential.options_for_create(
79
+ **keyword_arguments,
80
+ relying_party: self
81
+ )
82
+ end
83
+
84
+ def verify_registration(raw_credential, challenge, user_verification: nil)
85
+ webauthn_credential = WebAuthn::Credential.from_create(raw_credential, relying_party: self)
86
+
87
+ if webauthn_credential.verify(challenge, user_verification: user_verification)
88
+ webauthn_credential
89
+ end
90
+ end
91
+
92
+ def options_for_authentication(**keyword_arguments)
93
+ WebAuthn::Credential.options_for_get(
94
+ **keyword_arguments,
95
+ relying_party: self
96
+ )
97
+ end
98
+
99
+ def verify_authentication(
100
+ raw_credential,
101
+ challenge,
102
+ user_verification: nil,
103
+ public_key: nil,
104
+ sign_count: nil
105
+ )
106
+ webauthn_credential = WebAuthn::Credential.from_get(raw_credential, relying_party: self)
107
+
108
+ stored_credential = yield(webauthn_credential) if block_given?
109
+
110
+ if webauthn_credential.verify(
111
+ challenge,
112
+ public_key: public_key || stored_credential.public_key,
113
+ sign_count: sign_count || stored_credential.sign_count,
114
+ user_verification: user_verification
115
+ )
116
+ block_given? ? [webauthn_credential, stored_credential] : webauthn_credential
117
+ end
118
+ end
119
+ end
120
+ end
@@ -31,7 +31,10 @@ module WebAuthn
31
31
  @credential ||=
32
32
  begin
33
33
  hash = authenticator_data.send(:credential)
34
- WebAuthn::AuthenticatorData::AttestedCredentialData::Credential.new(hash[:id], hash[:public_key].serialize)
34
+ WebAuthn::AuthenticatorData::AttestedCredentialData::Credential.new(
35
+ id: hash[:id],
36
+ public_key: hash[:public_key].serialize
37
+ )
35
38
  end
36
39
  end
37
40
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebAuthn
4
- VERSION = "2.5.0"
4
+ VERSION = "3.0.0"
5
5
  end
data/webauthn.gemspec CHANGED
@@ -31,19 +31,17 @@ Gem::Specification.new do |spec|
31
31
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
32
  spec.require_paths = ["lib"]
33
33
 
34
- spec.required_ruby_version = ">= 2.4"
34
+ spec.required_ruby_version = ">= 2.5"
35
35
 
36
36
  spec.add_dependency "android_key_attestation", "~> 0.3.0"
37
37
  spec.add_dependency "awrence", "~> 1.1"
38
38
  spec.add_dependency "bindata", "~> 2.4"
39
39
  spec.add_dependency "cbor", "~> 0.5.9"
40
40
  spec.add_dependency "cose", "~> 1.1"
41
- spec.add_dependency "openssl", "~> 2.1"
41
+ spec.add_dependency "openssl", ">= 2.2"
42
42
  spec.add_dependency "safety_net_attestation", "~> 0.4.0"
43
- spec.add_dependency "securecompare", "~> 1.0"
44
- spec.add_dependency "tpm-key_attestation", "~> 0.10.0"
43
+ spec.add_dependency "tpm-key_attestation", "~> 0.12.0"
45
44
 
46
- spec.add_development_dependency "appraisal", "~> 2.4"
47
45
  spec.add_development_dependency "bundler", ">= 1.17", "< 3.0"
48
46
  spec.add_development_dependency "byebug", "~> 11.0"
49
47
  spec.add_development_dependency "rake", "~> 13.0"
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webauthn
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gonzalo Rodriguez
8
8
  - Braulio Martinez
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-03-14 00:00:00.000000000 Z
12
+ date: 2023-02-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: android_key_attestation
@@ -85,16 +85,16 @@ dependencies:
85
85
  name: openssl
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - "~>"
88
+ - - ">="
89
89
  - !ruby/object:Gem::Version
90
- version: '2.1'
90
+ version: '2.2'
91
91
  type: :runtime
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
- - - "~>"
95
+ - - ">="
96
96
  - !ruby/object:Gem::Version
97
- version: '2.1'
97
+ version: '2.2'
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: safety_net_attestation
100
100
  requirement: !ruby/object:Gem::Requirement
@@ -109,48 +109,20 @@ dependencies:
109
109
  - - "~>"
110
110
  - !ruby/object:Gem::Version
111
111
  version: 0.4.0
112
- - !ruby/object:Gem::Dependency
113
- name: securecompare
114
- requirement: !ruby/object:Gem::Requirement
115
- requirements:
116
- - - "~>"
117
- - !ruby/object:Gem::Version
118
- version: '1.0'
119
- type: :runtime
120
- prerelease: false
121
- version_requirements: !ruby/object:Gem::Requirement
122
- requirements:
123
- - - "~>"
124
- - !ruby/object:Gem::Version
125
- version: '1.0'
126
112
  - !ruby/object:Gem::Dependency
127
113
  name: tpm-key_attestation
128
114
  requirement: !ruby/object:Gem::Requirement
129
115
  requirements:
130
116
  - - "~>"
131
117
  - !ruby/object:Gem::Version
132
- version: 0.10.0
118
+ version: 0.12.0
133
119
  type: :runtime
134
120
  prerelease: false
135
121
  version_requirements: !ruby/object:Gem::Requirement
136
122
  requirements:
137
123
  - - "~>"
138
124
  - !ruby/object:Gem::Version
139
- version: 0.10.0
140
- - !ruby/object:Gem::Dependency
141
- name: appraisal
142
- requirement: !ruby/object:Gem::Requirement
143
- requirements:
144
- - - "~>"
145
- - !ruby/object:Gem::Version
146
- version: '2.4'
147
- type: :development
148
- prerelease: false
149
- version_requirements: !ruby/object:Gem::Requirement
150
- requirements:
151
- - - "~>"
152
- - !ruby/object:Gem::Version
153
- version: '2.4'
125
+ version: 0.12.0
154
126
  - !ruby/object:Gem::Dependency
155
127
  name: bundler
156
128
  requirement: !ruby/object:Gem::Requirement
@@ -266,10 +238,10 @@ extensions: []
266
238
  extra_rdoc_files: []
267
239
  files:
268
240
  - ".github/workflows/build.yml"
241
+ - ".github/workflows/git.yml"
269
242
  - ".gitignore"
270
243
  - ".rspec"
271
244
  - ".rubocop.yml"
272
- - Appraisals
273
245
  - CHANGELOG.md
274
246
  - CONTRIBUTING.md
275
247
  - Gemfile
@@ -279,9 +251,8 @@ files:
279
251
  - SECURITY.md
280
252
  - bin/console
281
253
  - bin/setup
254
+ - docs/advanced_configuration.md
282
255
  - docs/u2f_migration.md
283
- - gemfiles/openssl_2_1.gemfile
284
- - gemfiles/openssl_2_2.gemfile
285
256
  - lib/cose/rsapkcs1_algorithm.rb
286
257
  - lib/webauthn.rb
287
258
  - lib/webauthn/attestation_object.rb
@@ -325,7 +296,7 @@ files:
325
296
  - lib/webauthn/public_key_credential/user_entity.rb
326
297
  - lib/webauthn/public_key_credential_with_assertion.rb
327
298
  - lib/webauthn/public_key_credential_with_attestation.rb
328
- - lib/webauthn/security_utils.rb
299
+ - lib/webauthn/relying_party.rb
329
300
  - lib/webauthn/u2f_migrator.rb
330
301
  - lib/webauthn/version.rb
331
302
  - webauthn.gemspec
@@ -336,7 +307,7 @@ metadata:
336
307
  bug_tracker_uri: https://github.com/cedarcode/webauthn-ruby/issues
337
308
  changelog_uri: https://github.com/cedarcode/webauthn-ruby/blob/master/CHANGELOG.md
338
309
  source_code_uri: https://github.com/cedarcode/webauthn-ruby
339
- post_install_message:
310
+ post_install_message:
340
311
  rdoc_options: []
341
312
  require_paths:
342
313
  - lib
@@ -344,15 +315,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
344
315
  requirements:
345
316
  - - ">="
346
317
  - !ruby/object:Gem::Version
347
- version: '2.4'
318
+ version: '2.5'
348
319
  required_rubygems_version: !ruby/object:Gem::Requirement
349
320
  requirements:
350
321
  - - ">="
351
322
  - !ruby/object:Gem::Version
352
323
  version: '0'
353
324
  requirements: []
354
- rubygems_version: 3.2.14
355
- signing_key:
325
+ rubygems_version: 3.2.32
326
+ signing_key:
356
327
  specification_version: 4
357
328
  summary: WebAuthn ruby server library
358
329
  test_files: []
data/Appraisals DELETED
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- appraise "openssl_2_2" do
4
- gem "openssl", "~> 2.2.0"
5
- end
6
-
7
- appraise "openssl_2_1" do
8
- gem "openssl", "~> 2.1.0"
9
- end
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "openssl", "~> 2.1.0"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "openssl", "~> 2.2.0"
6
-
7
- gemspec path: "../"
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "securecompare"
4
-
5
- module WebAuthn
6
- module SecurityUtils
7
- # Constant time string comparison, for variable length strings.
8
- # This code was adapted from Rails ActiveSupport::SecurityUtils
9
- #
10
- # The values are first processed by SHA256, so that we don't leak length info
11
- # via timing attacks.
12
- def secure_compare(first_string, second_string)
13
- first_string_sha256 = ::Digest::SHA256.digest(first_string)
14
- second_string_sha256 = ::Digest::SHA256.digest(second_string)
15
-
16
- SecureCompare.compare(first_string_sha256, second_string_sha256) && first_string == second_string
17
- end
18
- module_function :secure_compare
19
- end
20
- end