webauthn 2.0.0.beta1 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +65 -13
  4. data/.travis.yml +22 -18
  5. data/Appraisals +4 -0
  6. data/CHANGELOG.md +72 -25
  7. data/CONTRIBUTING.md +0 -5
  8. data/README.md +172 -15
  9. data/SECURITY.md +4 -4
  10. data/gemfiles/openssl_2_2.gemfile +7 -0
  11. data/lib/cose/rsapkcs1_algorithm.rb +43 -0
  12. data/lib/webauthn/attestation_object.rb +43 -0
  13. data/lib/webauthn/attestation_statement.rb +20 -20
  14. data/lib/webauthn/attestation_statement/android_key.rb +28 -30
  15. data/lib/webauthn/attestation_statement/android_safetynet.rb +30 -20
  16. data/lib/webauthn/attestation_statement/base.rb +124 -14
  17. data/lib/webauthn/attestation_statement/fido_u2f.rb +13 -9
  18. data/lib/webauthn/attestation_statement/packed.rb +14 -42
  19. data/lib/webauthn/attestation_statement/tpm.rb +38 -54
  20. data/lib/webauthn/authenticator_assertion_response.rb +7 -36
  21. data/lib/webauthn/authenticator_attestation_response.rb +24 -46
  22. data/lib/webauthn/authenticator_data.rb +51 -51
  23. data/lib/webauthn/authenticator_data/attested_credential_data.rb +29 -50
  24. data/lib/webauthn/authenticator_response.rb +15 -10
  25. data/lib/webauthn/configuration.rb +23 -0
  26. data/lib/webauthn/credential.rb +4 -4
  27. data/lib/webauthn/credential_creation_options.rb +1 -1
  28. data/lib/webauthn/fake_authenticator.rb +7 -3
  29. data/lib/webauthn/fake_authenticator/attestation_object.rb +7 -3
  30. data/lib/webauthn/fake_authenticator/authenticator_data.rb +2 -4
  31. data/lib/webauthn/fake_client.rb +17 -4
  32. data/lib/webauthn/public_key.rb +68 -0
  33. data/lib/webauthn/public_key_credential.rb +13 -3
  34. data/lib/webauthn/public_key_credential/creation_options.rb +2 -2
  35. data/lib/webauthn/u2f_migrator.rb +5 -4
  36. data/lib/webauthn/version.rb +1 -1
  37. data/script/ci/install-openssl +7 -0
  38. data/script/ci/install-ruby +13 -0
  39. data/webauthn.gemspec +14 -9
  40. metadata +70 -42
  41. data/lib/android_safetynet/attestation_response.rb +0 -84
  42. data/lib/cose/algorithm.rb +0 -38
  43. data/lib/tpm/constants.rb +0 -22
  44. data/lib/tpm/s_attest.rb +0 -26
  45. data/lib/tpm/s_attest/s_certify_info.rb +0 -14
  46. data/lib/tpm/sized_buffer.rb +0 -13
  47. data/lib/tpm/t_public.rb +0 -32
  48. data/lib/tpm/t_public/s_ecc_parms.rb +0 -17
  49. data/lib/tpm/t_public/s_rsa_parms.rb +0 -17
  50. data/lib/webauthn/attestation_statement/android_key/authorization_list.rb +0 -39
  51. data/lib/webauthn/attestation_statement/android_key/key_description.rb +0 -37
  52. data/lib/webauthn/attestation_statement/tpm/cert_info.rb +0 -44
  53. data/lib/webauthn/attestation_statement/tpm/pub_area.rb +0 -85
  54. data/lib/webauthn/signature_verifier.rb +0 -65
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6181693e3c34f1ca289fb2056df36c35a5e144076288eef34e774e2dfc1794b5
4
- data.tar.gz: 87883fa3fe7c7bd5da885025b7a571dfedfdfe1c27c6a5c8edeee54956bd98bc
3
+ metadata.gz: 4094023fc463d77a38548e294121f819e874bfb1c075ca43b1fb38e41cfd53a2
4
+ data.tar.gz: f410f8d7e000822943be953265a32e8f81423908e6aff282486d5afa4ab62eb4
5
5
  SHA512:
6
- metadata.gz: a69f7870a89344a5d00b1c75b55dd6e25741719bf2fd79d03e83348530a964ef237f8330dea55edbb58b9fe5ee0522f2f41b5d9d46f7d975112b9dd8a05889bd
7
- data.tar.gz: 19b32618b9e83e2618abe361aca398933030fe2963502c8a9054dc291b22678107e3257be5d7a711bdf0d826dc1d444e28d726282fa6306abf336f675e3794df
6
+ metadata.gz: 23ea57e2264cc45024174e8d7a54bc3d4f373cca916c4453079d5cfccf46caa4dbc5aa4013a54404121274a35e71f97f90a061062a21ca270a8b58d474345fb8
7
+ data.tar.gz: 3b49c5b5b845fdcfc3b0b647a16aeab07ad219210e8e29835d171e387d6bcc4ac5fe08a4f9d2978ee6db1022363d1c2b06fe0a163a8625038aca51e1d274e903
data/.gitignore CHANGED
@@ -13,3 +13,4 @@
13
13
  /Gemfile.lock
14
14
  /gemfiles/*.gemfile.lock
15
15
  .byebug_history
16
+ /spec/conformance/metadata.zip
@@ -1,12 +1,16 @@
1
+ require:
2
+ - rubocop-rspec
3
+
1
4
  inherit_mode:
2
5
  merge:
3
6
  - AllowedNames
4
7
 
5
8
  AllCops:
6
- TargetRubyVersion: 2.3
9
+ TargetRubyVersion: 2.4
7
10
  DisabledByDefault: true
8
11
  Exclude:
9
12
  - "gemfiles/**/*"
13
+ - "vendor/**/*"
10
14
 
11
15
  Bundler:
12
16
  Enabled: true
@@ -17,18 +21,69 @@ Gemspec:
17
21
  Layout:
18
22
  Enabled: true
19
23
 
20
- Lint:
24
+ Layout/ClassStructure:
25
+ Enabled: true
26
+
27
+ Layout/FirstMethodArgumentLineBreak:
21
28
  Enabled: true
22
29
 
23
- Metrics/LineLength:
30
+ Layout/LineLength:
24
31
  Max: 120
25
32
  Exclude:
26
33
  - spec/support/seeds.rb
27
34
 
35
+ Layout/MultilineAssignmentLayout:
36
+ Enabled: true
37
+
38
+ Layout/MultilineMethodArgumentLineBreaks:
39
+ Enabled: true
40
+
41
+ Lint:
42
+ Enabled: true
43
+
28
44
  Naming:
29
45
  Enabled: true
30
46
 
31
- Naming/UncommunicativeMethodParamName:
47
+ RSpec/Be:
48
+ Enabled: true
49
+
50
+ RSpec/BeforeAfterAll:
51
+ Enabled: true
52
+
53
+ RSpec/EmptyExampleGroup:
54
+ Enabled: true
55
+
56
+ RSpec/EmptyLineAfterExample:
57
+ Enabled: true
58
+
59
+ RSpec/EmptyLineAfterExampleGroup:
60
+ Enabled: true
61
+
62
+ RSpec/EmptyLineAfterFinalLet:
63
+ Enabled: true
64
+
65
+ RSpec/EmptyLineAfterHook:
66
+ Enabled: true
67
+
68
+ RSpec/EmptyLineAfterSubject:
69
+ Enabled: true
70
+
71
+ RSpec/HookArgument:
72
+ Enabled: true
73
+
74
+ RSpec/LeadingSubject:
75
+ Enabled: true
76
+
77
+ RSpec/NamedSubject:
78
+ Enabled: true
79
+
80
+ RSpec/ScatteredLet:
81
+ Enabled: true
82
+
83
+ RSpec/ScatteredSetup:
84
+ Enabled: true
85
+
86
+ Naming/MethodParameterName:
32
87
  AllowedNames:
33
88
  - rp
34
89
 
@@ -38,9 +93,6 @@ Security:
38
93
  Style/BlockComments:
39
94
  Enabled: true
40
95
 
41
- Style/BracesAroundHashParameters:
42
- Enabled: true
43
-
44
96
  Style/CaseEquality:
45
97
  Enabled: true
46
98
 
@@ -146,9 +198,15 @@ Style/RedundantException:
146
198
  Style/RedundantFreeze:
147
199
  Enabled: true
148
200
 
201
+ Style/RedundantInterpolation:
202
+ Enabled: true
203
+
149
204
  Style/RedundantParentheses:
150
205
  Enabled: true
151
206
 
207
+ Style/RedundantPercentQ:
208
+ Enabled: true
209
+
152
210
  Style/RedundantReturn:
153
211
  Enabled: true
154
212
 
@@ -182,12 +240,6 @@ Style/TrailingMethodEndStatement:
182
240
  Style/TrivialAccessors:
183
241
  Enabled: true
184
242
 
185
- Style/UnneededInterpolation:
186
- Enabled: true
187
-
188
- Style/UnneededPercentQ:
189
- Enabled: true
190
-
191
243
  Style/UnpackFirst:
192
244
  Enabled: true
193
245
 
@@ -1,35 +1,39 @@
1
- dist: xenial
1
+ dist: bionic
2
2
  language: ruby
3
- cache: bundler
4
3
 
5
- rvm:
6
- - ruby-head
7
- - 2.7.0-preview1
8
- - 2.6.4
9
- - 2.5.6
10
- - 2.4.7
11
- - 2.3.8
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
12
20
 
13
21
  gemfile:
14
22
  - gemfiles/cose_head.gemfile
15
23
  - gemfiles/openssl_head.gemfile
24
+ - gemfiles/openssl_2_2.gemfile
16
25
  - gemfiles/openssl_2_1.gemfile
17
26
  - gemfiles/openssl_2_0.gemfile
18
27
 
19
28
  matrix:
20
29
  fast_finish: true
21
30
  allow_failures:
22
- - rvm: ruby-head
23
- - rvm: 2.7.0-preview1
31
+ - env: LIBSSL=1.1 RB=ruby-head
32
+ - env: LIBSSL=1.0 RB=ruby-head
24
33
  - gemfile: gemfiles/cose_head.gemfile
25
34
  - gemfile: gemfiles/openssl_head.gemfile
26
35
 
27
36
  before_install:
28
- - wget http://archive.ubuntu.com/ubuntu/pool/universe/f/faketime/libfaketime_0.9.7-3_amd64.deb
29
- - sudo dpkg -i libfaketime_0.9.7-3_amd64.deb
37
+ - ./script/ci/install-openssl
38
+ - ./script/ci/install-ruby
30
39
  - gem install bundler -v "~> 2.0"
31
-
32
- before_script:
33
- - export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1
34
- - export DONT_FAKE_MONOTONIC=1
35
- - export FAKETIME_NO_CACHE=1
data/Appraisals CHANGED
@@ -8,6 +8,10 @@ appraise "openssl_head" do
8
8
  gem "openssl", git: "https://github.com/ruby/openssl"
9
9
  end
10
10
 
11
+ appraise "openssl_2_2" do
12
+ gem "openssl", "~> 2.2.0"
13
+ end
14
+
11
15
  appraise "openssl_2_1" do
12
16
  gem "openssl", "~> 2.1.0"
13
17
  end
@@ -1,6 +1,39 @@
1
1
  # Changelog
2
2
 
3
- ## [v2.0.0.beta1] - 2019-09-16
3
+ ## [v2.3.0] - 2020-06-27
4
+
5
+ ### Added
6
+
7
+ - Ability to access extension outputs with `PublicKeyCredential#client_extension_outputs` and `PublicKeyCredential#authenticator_extension_outputs` ([@santiagorodriguez96])
8
+
9
+ ## [v2.2.1] - 2020-06-06
10
+
11
+ ### Fixed
12
+
13
+ - Fixed compatibility with OpenSSL-C (libssl) v1.0.2 ([@santiagorodriguez96])
14
+
15
+ ## [v2.2.0] - 2020-03-14
16
+
17
+ ### Added
18
+
19
+ - Verification step that checks the received credential public key algorithm during registration matches one of the configured algorithms
20
+ - [EXPERIMENTAL] Attestation trustworthiness verification default steps for "tpm", "android-key" and "android-safetynet" ([@bdewater], [@padulafacundo]). Still manual configuration needed for "packed" and "fido-u2f".
21
+
22
+ Note: Expect possible breaking changes for "EXPERIMENTAL" features.
23
+
24
+ ## [v2.1.0] - 2019-12-30
25
+
26
+ ### Added
27
+
28
+ - Ability to convert stored credential public key back to a ruby object with `WebAuthn::PublicKey.deserialize(stored_public_key)`, included the validation during de-serialization ([@ssuttner], [@padulafacundo])
29
+ - Improved TPM attestation validation by checking "Subject Alternative Name" ([@bdewater])
30
+ - Improved SafetyNet attestation validation by checking timestamp ([@padulafacundo])
31
+ - [EXPERIMENTAL] Ability to optionally "Assess the attestation trustworthiness" during registration by setting `acceptable_attestation_types` and `attestation_root_certificates_finders` configuration values ([@padulafacundo])
32
+ - Ruby 2.7 support without warnings
33
+
34
+ Note: Expect possible breaking changes for "EXPERIMENTAL" features.
35
+
36
+ ## [v2.0.0] - 2019-10-03
4
37
 
5
38
  ### Added
6
39
 
@@ -13,7 +46,7 @@
13
46
  - All the above automatically handle encoding/decoding for necessary values. The specific encoding scheme can
14
47
  be set (or even turned off) in `WebAutnn.configuration.encoding=`. Defaults to `:base64url`.
15
48
  - `WebAuthn::FakeClient#get` better fakes a real client by including `userHandle` in the returned hash.
16
- - Expose AAGUID and attestationCertificateKey for MDS lookup during attestation (@bdwater)
49
+ - Expose AAGUID and attestationCertificateKey for MDS lookup during attestation ([@bdewater])
17
50
 
18
51
  ### Changed
19
52
 
@@ -21,8 +54,9 @@
21
54
  Please replace with `public_key:` and `sign_count:` keyword arguments. If you're not performing sign count
22
55
  verification, signal opt-out with `sign_count: false`.
23
56
 
24
- - `WebAuthn::FakeClient#create` and `WebAuthn::FakeClient#get` better fakes a real client by using camelBack string
25
- keys instead of snake_case symbol keys in the returned hash.
57
+ - `WebAuthn::FakeClient#create` and `WebAuthn::FakeClient#get` better fakes a real client by using lowerCamelCase
58
+ string keys instead of snake_case symbol keys in the returned hash.
59
+
26
60
  - `WebAuthn::FakeClient#create` and `WebAuthn::FakeClient#get` better fakes a real client by not padding the
27
61
  returned base64url-encoded `id` value.
28
62
 
@@ -45,8 +79,8 @@ pass it.
45
79
  Please replace with `public_key:` and `sign_count:` keyword arguments. If you're not performing sign count
46
80
  verification, signal opt-out with `sign_count: false`.
47
81
 
48
- - `WebAuthn::FakeClient#create` and `WebAuthn::FakeClient#get` better fakes a real client by using camelBack string
49
- keys instead of snake_case symbol keys in the returned hash.
82
+ - `WebAuthn::FakeClient#create` and `WebAuthn::FakeClient#get` better fakes a real client by using lowerCamelCase
83
+ string keys instead of snake_case symbol keys in the returned hash.
50
84
 
51
85
  - `WebAuthn::FakeClient#create` and `WebAuthn::FakeClient#get` better fakes a real client by not padding the
52
86
  returned base64url-encoded `id` value.
@@ -55,23 +89,23 @@ returned base64url-encoded `id` value.
55
89
 
56
90
  ### Added
57
91
 
58
- - Ability to migrate U2F credentials to WebAuthn ([#211](https://github.com/cedarcode/webauthn-ruby/pull/211)) (@bdewater + @jdongelmans)
59
- - Ability to skip attestation statement verification ([#219](https://github.com/cedarcode/webauthn-ruby/pull/219)) (@MaximeNdutiye)
60
- - Ability to configure default credential options timeout ([#243](https://github.com/cedarcode/webauthn-ruby/pull/243)) (@MaximeNdutiye)
92
+ - Ability to migrate U2F credentials to WebAuthn ([#211](https://github.com/cedarcode/webauthn-ruby/pull/211)) ([@bdewater] + [@jdongelmans])
93
+ - Ability to skip attestation statement verification ([#219](https://github.com/cedarcode/webauthn-ruby/pull/219)) ([@MaximeNdutiye])
94
+ - Ability to configure default credential options timeout ([#243](https://github.com/cedarcode/webauthn-ruby/pull/243)) ([@MaximeNdutiye])
61
95
  - AttestedCredentialData presence verification ([#237](https://github.com/cedarcode/webauthn-ruby/pull/237))
62
96
  - FakeClient learns how to increment sign count ([#225](https://github.com/cedarcode/webauthn-ruby/pull/225))
63
97
 
64
98
  ### Fixed
65
99
 
66
- - Properly verify SafetyNet certificates from input ([#233](https://github.com/cedarcode/webauthn-ruby/pull/233)) (@bdewater)
67
- - FakeClient default origin URL ([#242](https://github.com/cedarcode/webauthn-ruby/pull/242)) (@kalebtesfay)
100
+ - Properly verify SafetyNet certificates from input ([#233](https://github.com/cedarcode/webauthn-ruby/pull/233)) ([@bdewater])
101
+ - FakeClient default origin URL ([#242](https://github.com/cedarcode/webauthn-ruby/pull/242)) ([@kalebtesfay])
68
102
 
69
103
  ## [v1.17.0] - 2019-06-18
70
104
 
71
105
  ### Added
72
106
 
73
- - Support ES384, ES512, PS384, PS512, RS384 and RS512 credentials. Off by default. Enable by adding any of them to `WebAuthn.configuration.algorithms` array. Thank you @bdewater.
74
- - Support [Signature Counter](https://www.w3.org/TR/webauthn/#signature-counter) verification. Thank you @bdewater.
107
+ - Support ES384, ES512, PS384, PS512, RS384 and RS512 credentials. Off by default. Enable by adding any of them to `WebAuthn.configuration.algorithms` array ([@bdewater])
108
+ - Support [Signature Counter](https://www.w3.org/TR/webauthn/#signature-counter) verification ([@bdewater])
75
109
 
76
110
  ## [v1.16.0] - 2019-06-13
77
111
 
@@ -79,7 +113,7 @@ returned base64url-encoded `id` value.
79
113
 
80
114
  - Ability to enforce [user verification](https://www.w3.org/TR/webauthn/#user-verification) with extra argument in the `#verify` method.
81
115
  - Support RS1 (RSA w/ SHA-1) credentials. Off by default. Enable by adding `"RS1"` to `WebAuthn.configuration.algorithms` array.
82
- - Support PS256 (RSA Probabilistic Signature Scheme w/ SHA-256) credentials. On by default. Thank you @bdewater.
116
+ - Support PS256 (RSA Probabilistic Signature Scheme w/ SHA-256) credentials. On by default ([@bdewater])
83
117
 
84
118
  ## [v1.15.0] - 2019-05-16
85
119
 
@@ -101,11 +135,11 @@ returned base64url-encoded `id` value.
101
135
  - Verify 'none' attestation statement is really empty.
102
136
  - Verify 'packed' attestation statement certificates start/end dates.
103
137
  - Verify 'packed' attestation statement signature algorithm.
104
- - Verify 'fiod-u2f attestation statement AAGUID is zeroed out. Thank you @bdewater.
138
+ - Verify 'fiod-u2f attestation statement AAGUID is zeroed out ([@bdewater])
105
139
  - Verify 'android-key' attestation statement signature algorithm.
106
140
  - Verify assertion response signature algorithm.
107
141
  - Verify collectedClientData.tokenBinding format.
108
- - `WebAuthn.credential_creation_options` now accept `rp_name`, `user_id`, `user_name` and `display_name` as keyword arguments. Thank you @bdewater.
142
+ - `WebAuthn.credential_creation_options` now accept `rp_name`, `user_id`, `user_name` and `display_name` as keyword arguments ([@bdewater])
109
143
 
110
144
  ## [v1.12.0] - 2019-04-03
111
145
 
@@ -127,11 +161,11 @@ Note #2: You don't need to do any convesion before passing the public key in `Au
127
161
 
128
162
  ### Added
129
163
 
130
- - `WebAuthn::AuthenticatorAttestationResponse#verify` supports `android-key` attestation statements. Thank you @bdewater!
164
+ - `WebAuthn::AuthenticatorAttestationResponse#verify` supports `android-key` attestation statements ([@bdewater])
131
165
 
132
166
  ### Fixed
133
167
 
134
- - Verify matching AAGUID if needed when verifying `packed` attestation statements. Thank you @bdewater!
168
+ - Verify matching AAGUID if needed when verifying `packed` attestation statements ([@bdewater])
135
169
 
136
170
  ## [v1.10.0] - 2019-03-05
137
171
 
@@ -149,7 +183,7 @@ Note #2: You don't need to do any convesion before passing the public key in `Au
149
183
 
150
184
  ### Added
151
185
 
152
- - Make challenge validation inside `#valid?` method resistant to timing attacks. Thank you @tomek-bt!
186
+ - Make challenge validation inside `#valid?` method resistant to timing attacks (@tomek-bt)
153
187
  - Support for ruby 2.6
154
188
 
155
189
  ### Changed
@@ -161,7 +195,7 @@ Note #2: You don't need to do any convesion before passing the public key in `Au
161
195
  ### Added
162
196
 
163
197
  - _Registration_ ceremony
164
- - `WebAuthn::AuthenticatorAttestationResponse` exposes attestation type and trust path via `#attestation_type` and `#attestation_trust_path` methods. Thank you @bdewater!
198
+ - `WebAuthn::AuthenticatorAttestationResponse` exposes attestation type and trust path via `#attestation_type` and `#attestation_trust_path` methods ([@bdewater])
165
199
 
166
200
  ## [v1.6.0] - 2018-11-01
167
201
 
@@ -173,21 +207,21 @@ Note #2: You don't need to do any convesion before passing the public key in `Au
173
207
 
174
208
  ### Added
175
209
 
176
- - Works with ruby 2.3. Thank you @bdewater!
210
+ - Works with ruby 2.3 ([@bdewater])
177
211
 
178
212
  ## [v1.4.0] - 2018-10-11
179
213
 
180
214
  ### Added
181
215
 
182
216
  - _Registration_ ceremony
183
- - `WebAuthn::AuthenticatorAttestationResponse.valid?` supports `android-safetynet` attestation statements. Thank you @bdewater!
217
+ - `WebAuthn::AuthenticatorAttestationResponse.valid?` supports `android-safetynet` attestation statements ([@bdewater])
184
218
 
185
219
  ## [v1.3.0] - 2018-10-11
186
220
 
187
221
  ### Added
188
222
 
189
223
  - _Registration_ ceremony
190
- - `WebAuthn::AuthenticatorAttestationResponse.valid?` supports `packed` attestation statements. Thank you @sorah!
224
+ - `WebAuthn::AuthenticatorAttestationResponse.valid?` supports `packed` attestation statements ([@sorah])
191
225
 
192
226
  ## [v1.2.0] - 2018-10-08
193
227
 
@@ -205,7 +239,7 @@ Note: Both additions should help making it compatible with Chrome for Android 70
205
239
  ### Added
206
240
 
207
241
  - _Registration_ ceremony
208
- - `WebAuthn::AuthenticatorAttestationResponse.valid?` optionally accepts rp_id. Thank you @sorah!
242
+ - `WebAuthn::AuthenticatorAttestationResponse.valid?` optionally accepts rp_id ([@sorah])
209
243
  - _Authentication_ ceremony
210
244
  - `WebAuthn::AuthenticatorAssertionResponse.valid?` optionally accepts rp_id.
211
245
 
@@ -260,7 +294,11 @@ Note: Both additions should help making it compatible with Chrome for Android 70
260
294
  - `WebAuthn::AuthenticatorAttestationResponse.valid?` can be used to validate fido-u2f attestations returned by the browser
261
295
  - Works with ruby 2.5
262
296
 
263
- [v2.0.0.beta1]: https://github.com/cedarcode/webauthn-ruby/compare/v1.18.0...v2.0.0.beta1/
297
+ [v2.3.0]: https://github.com/cedarcode/webauthn-ruby/compare/v2.2.1...v2.3.0/
298
+ [v2.2.1]: https://github.com/cedarcode/webauthn-ruby/compare/v2.2.0...v2.2.1/
299
+ [v2.2.0]: https://github.com/cedarcode/webauthn-ruby/compare/v2.1.0...v2.2.0/
300
+ [v2.1.0]: https://github.com/cedarcode/webauthn-ruby/compare/v2.0.0...v2.1.0/
301
+ [v2.0.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.18.0...v2.0.0/
264
302
  [v1.18.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.17.0...v1.18.0/
265
303
  [v1.17.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.16.0...v1.17.0/
266
304
  [v1.16.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.15.0...v1.16.0/
@@ -282,3 +320,12 @@ Note: Both additions should help making it compatible with Chrome for Android 70
282
320
  [v1.0.0]: https://github.com/cedarcode/webauthn-ruby/compare/v0.2.0...v1.0.0/
283
321
  [v0.2.0]: https://github.com/cedarcode/webauthn-ruby/compare/v0.1.0...v0.2.0/
284
322
  [v0.1.0]: https://github.com/cedarcode/webauthn-ruby/compare/v0.0.0...v0.1.0/
323
+
324
+ [@bdewater]: https://github.com/bdewater
325
+ [@jdongelmans]: https://github.com/jdongelmans
326
+ [@kalebtesfay]: https://github.com/kalebtesfay
327
+ [@MaximeNdutiye]: https://github.com/MaximeNdutiye
328
+ [@sorah]: https://github.com/sorah
329
+ [@ssuttner]: https://github.com/ssuttner
330
+ [@padulafacundo]: https://github.com/padulafacundo
331
+ [@santiagorodriguez96]: https://github.com/santiagorodriguez96
@@ -14,11 +14,6 @@
14
14
 
15
15
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake` to run the tests and code-style checks. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
16
16
 
17
- Some tests require stubbing time with [libfaketime](https://github.com/wolfcw/libfaketime) in order to pass, otherwise they're skipped. You can install this library with your package manager. Follow libfaketime's instructions for your OS to preload the library before running the tests, and use the `DONT_FAKE_MONOTONIC=1 FAKETIME_NO_CACHE=1` options. E.g. when installed via homebrew on macOS:
18
- ```shell
19
- DYLD_INSERT_LIBRARIES=/usr/local/Cellar/libfaketime/2.9.7_1/lib/faketime/libfaketime.1.dylib DYLD_FORCE_FLAT_NAMESPACE=1 DONT_FAKE_MONOTONIC=1 FAKETIME_NO_CACHE=1 bundle exec rspec
20
- ```
21
-
22
17
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
23
18
 
24
19
  ### Styleguide
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  __Note__: You are viewing the README for the development version of webauthn-ruby.
2
- For the current release version see https://github.com/cedarcode/webauthn-ruby/blob/1-stable/README.md.
2
+ For the current release version see https://github.com/cedarcode/webauthn-ruby/blob/2-stable/README.md.
3
3
 
4
4
  # webauthn-ruby
5
5
 
@@ -64,12 +64,12 @@ Known conformant pairs are, for example:
64
64
  - Google Chrome for Android 70+ and Android's Fingerprint-based platform authenticator
65
65
  - Microsoft Edge and Windows 10 platform authenticator
66
66
  - Mozilla Firefox for Desktop and Yubico's Security Key roaming authenticator via USB
67
+ - Safari in iOS 13.3+ and YubiKey 5 NFC via NFC
67
68
 
68
- For a detailed picture about what is conformant and what not, you can refer to:
69
-
70
- - [apowers313/fido2-webauthn-status](https://github.com/apowers313/fido2-webauthn-status)
71
- - [FIDO certified products](https://fidoalliance.org/certification/fido-certified-products)
69
+ For a complete list:
72
70
 
71
+ - User Agents (Clients): [Can I Use: Web Authentication API](https://caniuse.com/#search=webauthn)
72
+ - Authenticators: [FIDO certified products](https://fidoalliance.org/certification/fido-certified-products) (search for Type=Authenticator and Specification=FIDO2)
73
73
 
74
74
  ## Install
75
75
 
@@ -108,11 +108,11 @@ WebAuthn.configure do |config|
108
108
  config.rp_name = "Example Inc."
109
109
 
110
110
  # Optionally configure a client timeout hint, in milliseconds.
111
- # This hint specifies how long the browser should wait for an
112
- # attestation or an assertion response.
111
+ # This hint specifies how long the browser should wait for any
112
+ # interaction with the user.
113
113
  # This hint may be overridden by the browser.
114
114
  # https://www.w3.org/TR/webauthn/#dom-publickeycredentialcreationoptions-timeout
115
- config.credential_options_timeout = 120000
115
+ # config.credential_options_timeout = 120_000
116
116
 
117
117
  # You can optionally specify a different Relying Party ID
118
118
  # (https://www.w3.org/TR/webauthn/#relying-party-identifier)
@@ -127,7 +127,12 @@ WebAuthn.configure do |config|
127
127
  # used in your client-side (user agent) code before sending the credential to the server.
128
128
  # Supported values: `:base64url` (default), `:base64` or `false` to disable all encoding.
129
129
  #
130
- # config.encoding = false
130
+ # config.encoding = :base64url
131
+
132
+ # Possible values: "ES256", "ES384", "ES512", "PS256", "PS384", "PS512", "RS256", "RS384", "RS512", "RS1"
133
+ # Default: ["ES256", "PS256", "RS256"]
134
+ #
135
+ # config.algorithms << "ES384"
131
136
  end
132
137
  ```
133
138
 
@@ -145,7 +150,7 @@ if !user.webauthn_id
145
150
  end
146
151
 
147
152
  options = WebAuthn::Credential.options_for_create(
148
- user: { id: user.webauthn_id, name: user.name }
153
+ user: { id: user.webauthn_id, name: user.name },
149
154
  exclude: user.credentials.map { |c| c.webauthn_id }
150
155
  )
151
156
 
@@ -247,25 +252,177 @@ rescue WebAuthn::Error => e
247
252
  end
248
253
  ```
249
254
 
255
+ ### Extensions
256
+
257
+ > The mechanism for generating public key credentials, as well as requesting and generating Authentication assertions, as defined in Web Authentication API, can be extended to suit particular use cases. Each case is addressed by defining a registration extension and/or an authentication extension.
258
+
259
+ > When creating a public key credential or requesting an authentication assertion, a WebAuthn Relying Party can request the use of a set of extensions. These extensions will be invoked during the requested ceremony if they are supported by the WebAuthn Client and/or the WebAuthn Authenticator. The Relying Party sends the client extension input for each extension in the get() call (for authentication extensions) or create() call (for registration extensions) to the WebAuthn client. [[source](https://www.w3.org/TR/webauthn-2/#sctn-extensions)]
260
+
261
+ Extensions can be requested in the initiation phase in both Credential Registration and Authentication ceremonies by adding the extension parameter when generating the options for create/get:
262
+
263
+ ```ruby
264
+ # Credential Registration
265
+ creation_options = WebAuthn::Credential.options_for_create(
266
+ user: { id: user.webauthn_id, name: user.name },
267
+ exclude: user.credentials.map { |c| c.webauthn_id },
268
+ extensions: { appidExclude: domain.to_s }
269
+ )
270
+
271
+ # OR
272
+
273
+ # Credential Authentication
274
+ options = WebAuthn::Credential.options_for_get(
275
+ allow: user.credentials.map { |c| c.webauthn_id },
276
+ extensions: { appid: domain.to_s }
277
+ )
278
+ ```
279
+
280
+ Consequently, after these `options` are sent to the WebAuthn client:
281
+
282
+ > The WebAuthn client performs client extension processing for each extension that the client supports, and augments the client data as specified by each extension, by including the extension identifier and client extension output values.
283
+
284
+ > For authenticator extensions, as part of the client extension processing, the client also creates the CBOR authenticator extension input value for each extension (often based on the corresponding client extension input value), and passes them to the authenticator in the create() call (for registration extensions) or the get() call (for authentication extensions).
285
+
286
+ > The authenticator, in turn, performs additional processing for the extensions that it supports, and returns the CBOR authenticator extension output for each as specified by the extension. Part of the client extension processing for authenticator extensions is to use the authenticator extension output as an input to creating the client extension output. [[source](https://www.w3.org/TR/webauthn-2/#sctn-extensions)]
287
+
288
+ Finally, you can check the values returned for each extension by calling `client_extension_outputs` and `authenticator_extension_outputs` respectively.
289
+ For example, following the initialization phase for the Credential Authentication ceremony specified in the above example:
290
+
291
+ ```ruby
292
+ webauthn_credential = WebAuthn::Credential.from_get(credential_get_result_hash)
293
+
294
+ webauthn_credential.client_extension_outputs #=> { "appid" => true }
295
+ webauthn_credential.authenticator_extension_outputs #=> nil
296
+ ```
297
+
298
+ A list of all currently defined extensions:
299
+
300
+ - [Last published version](https://www.w3.org/TR/webauthn-2/#sctn-defined-extensions)
301
+ - [Next version (in draft)](https://w3c.github.io/webauthn/#sctn-defined-extensions)
302
+
250
303
  ## API
251
304
 
252
- _Pending_
305
+ #### `WebAuthn.generate_user_id`
306
+
307
+ Generates a [WebAuthn User Handle](https://www.w3.org/TR/webauthn-2/#user-handle) that follows the WebAuthn spec recommendations.
308
+
309
+ ```ruby
310
+ WebAuthn.generate_user_id # "lWoMZTGf_ml2RoY5qPwbwrkxrvTqWjGOxEoYBgxft3zG-LlrICvE-y8bxFi06zMyIOyNsJoWx4Fa2TOqoRmnxA"
311
+ ```
312
+
313
+ #### `WebAuthn::Credential.options_for_create(options)`
314
+
315
+ Helper method to build the necessary [PublicKeyCredentialCreationOptions](https://www.w3.org/TR/webauthn-2/#dictdef-publickeycredentialcreationoptions)
316
+ to be used in the client-side code to call `navigator.credentials.create({ "publicKey": publicKeyCredentialCreationOptions })`.
317
+
318
+ ```ruby
319
+ creation_options = WebAuthn::Credential.options_for_create(
320
+ user: { id: user.webauthn_id, name: user.name }
321
+ exclude: user.credentials.map { |c| c.webauthn_id }
322
+ )
323
+
324
+ # Store the newly generated challenge somewhere so you can have it
325
+ # for the verification phase.
326
+ session[:creation_challenge] = creation_options.challenge
327
+
328
+ # Send `creation_options` back to the browser, so that they can be used
329
+ # to call `navigator.credentials.create({ "publicKey": creationOptions })`
330
+ #
331
+ # You can call `creation_options.as_json` to get a ruby hash with a JSON representation if needed.
332
+
333
+ # If inside a Rails controller, `render json: creation_options` will just work.
334
+ # I.e. it will encode and convert the options to JSON automatically.
335
+ ```
253
336
 
254
- ## Attestation Statement Formats
337
+ #### `WebAuthn::Credential.options_for_get([options])`
338
+
339
+ Helper method to build the necessary [PublicKeyCredentialRequestOptions](https://www.w3.org/TR/webauthn-2/#dictdef-publickeycredentialrequestoptions)
340
+ to be used in the client-side code to call `navigator.credentials.get({ "publicKey": publicKeyCredentialRequestOptions })`.
341
+
342
+ ```ruby
343
+ request_options = WebAuthn::Credential.options_for_get(allow: user.credentials.map { |c| c.webauthn_id })
344
+
345
+ # Store the newly generated challenge somewhere so you can have it
346
+ # for the verification phase.
347
+ session[:authentication_challenge] = request_options.challenge
348
+
349
+ # Send `request_options` back to the browser, so that they can be used
350
+ # to call `navigator.credentials.get({ "publicKey": requestOptions })`
351
+
352
+ # You can call `request_options.as_json` to get a ruby hash with a JSON representation if needed.
353
+
354
+ # If inside a Rails controller, `render json: request_options` will just work.
355
+ # I.e. it will encode and convert the options to JSON automatically.
356
+ ```
357
+
358
+ #### `WebAuthn::Credential.from_create(credential_create_result)`
359
+
360
+ ```ruby
361
+ credential_with_attestation = WebAuthn::Credential.from_create(params[:publicKeyCredential])
362
+ ```
363
+
364
+ #### `WebAuthn::Credential.from_get(credential_get_result)`
365
+
366
+ ```ruby
367
+ credential_with_assertion = WebAuthn::Credential.from_get(params[:publicKeyCredential])
368
+ ```
369
+
370
+ #### `PublicKeyCredentialWithAttestation#verify(challenge)`
371
+
372
+ Verifies the created WebAuthn credential is [valid](https://www.w3.org/TR/webauthn-2/#sctn-registering-a-new-credential).
373
+
374
+ ```ruby
375
+ credential_with_attestation.verify(session[:creation_challenge])
376
+ ```
377
+
378
+ #### `PublicKeyCredentialWithAssertion#verify(challenge, public_key:, sign_count:)`
379
+
380
+ Verifies the asserted WebAuthn credential is [valid](https://www.w3.org/TR/webauthn-2/#sctn-verifying-assertion).
381
+
382
+ Mainly, that the client provided a valid cryptographic signature for the corresponding stored credential public
383
+ key, among other extra validations.
384
+
385
+ ```ruby
386
+ credential_with_assertion.verify(
387
+ session[:authentication_challenge],
388
+ public_key: stored_credential.public_key,
389
+ sign_count: stored_credential.sign_count
390
+ )
391
+ ```
392
+
393
+ #### `PublicKeyCredential#client_extension_outputs`
394
+
395
+ ```ruby
396
+ credential = WebAuthn::Credential.from_create(params[:publicKeyCredential])
397
+
398
+ credential.client_extension_outputs
399
+ ```
400
+
401
+ #### `PublicKeyCredential#authenticator_extension_outputs`
402
+
403
+ ```ruby
404
+ credential = WebAuthn::Credential.from_create(params[:publicKeyCredential])
405
+
406
+ credential.authenticator_extension_outputs
407
+ ```
408
+
409
+ ## Attestation
410
+
411
+ ### Attestation Statement Format
255
412
 
256
413
  | Attestation Statement Format | Supported? |
257
414
  | -------- | :--------: |
258
415
  | packed (self attestation) | Yes |
259
416
  | packed (x5c attestation) | Yes |
260
- | packed (ECDAA attestation) | No |
261
417
  | tpm (x5c attestation) | Yes |
262
- | tpm (ECDAA attestation) | No |
263
418
  | android-key | Yes |
264
419
  | android-safetynet | Yes |
265
420
  | fido-u2f | Yes |
266
421
  | none | Yes |
267
422
 
268
- NOTE: Be aware that it is up to you to do "trust path validation" (steps 15 and 16 in [Registering a new credential](https://www.w3.org/TR/webauthn/#registering-a-new-credential)) if that's a requirement of your Relying Party policy. The gem doesn't perform that validation for you right now.
423
+ ### Attestation Types
424
+
425
+ You can define what trust policy to enforce by setting `acceptable_attestation_types` config to a subset of `['None', 'Self', 'Basic', 'AttCA', 'Basic_or_AttCA']` and `attestation_root_certificates_finders` to an object that responds to `#find` and returns the corresponding root certificate for each registration. The `#find` method will be called passing keyword arguments `attestation_format`, `aaguid` and `attestation_certificate_key_id`.
269
426
 
270
427
  ## Testing Your Integration
271
428