webauthn 1.18.0 → 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -0
- data/.travis.yml +7 -3
- data/Appraisals +8 -0
- data/CHANGELOG.md +52 -0
- data/README.md +88 -80
- data/SECURITY.md +18 -0
- data/gemfiles/cose_head.gemfile +7 -0
- data/gemfiles/openssl_head.gemfile +7 -0
- data/lib/webauthn.rb +9 -1
- data/lib/webauthn/attestation_statement/android_safetynet.rb +4 -4
- data/lib/webauthn/attestation_statement/base.rb +4 -4
- data/lib/webauthn/attestation_statement/fido_u2f.rb +1 -2
- data/lib/webauthn/authenticator_assertion_response.rb +33 -35
- data/lib/webauthn/authenticator_attestation_response.rb +30 -0
- data/lib/webauthn/authenticator_data.rb +3 -1
- data/lib/webauthn/authenticator_data/attested_credential_data.rb +1 -0
- data/lib/webauthn/authenticator_response.rb +1 -2
- data/lib/webauthn/client_data.rb +2 -1
- data/lib/webauthn/configuration.rb +9 -0
- data/lib/webauthn/credential.rb +26 -0
- data/lib/webauthn/credential_creation_options.rb +5 -1
- data/lib/webauthn/credential_request_options.rb +5 -0
- data/lib/webauthn/encoder.rb +8 -1
- data/lib/webauthn/fake_authenticator.rb +1 -0
- data/lib/webauthn/fake_client.rb +26 -22
- data/lib/webauthn/public_key_credential.rb +10 -50
- data/lib/webauthn/public_key_credential/creation_options.rb +92 -0
- data/lib/webauthn/public_key_credential/entity.rb +44 -0
- data/lib/webauthn/public_key_credential/options.rb +72 -0
- data/lib/webauthn/public_key_credential/request_options.rb +36 -0
- data/lib/webauthn/public_key_credential/rp_entity.rb +23 -0
- data/lib/webauthn/public_key_credential/user_entity.rb +24 -0
- data/lib/webauthn/public_key_credential_with_assertion.rb +35 -0
- data/lib/webauthn/public_key_credential_with_attestation.rb +30 -0
- data/lib/webauthn/u2f_migrator.rb +1 -1
- data/lib/webauthn/version.rb +1 -1
- data/webauthn.gemspec +3 -2
- metadata +33 -8
- data/webauthn-ruby.png +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6181693e3c34f1ca289fb2056df36c35a5e144076288eef34e774e2dfc1794b5
|
4
|
+
data.tar.gz: 87883fa3fe7c7bd5da885025b7a571dfedfdfe1c27c6a5c8edeee54956bd98bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a69f7870a89344a5d00b1c75b55dd6e25741719bf2fd79d03e83348530a964ef237f8330dea55edbb58b9fe5ee0522f2f41b5d9d46f7d975112b9dd8a05889bd
|
7
|
+
data.tar.gz: 19b32618b9e83e2618abe361aca398933030fe2963502c8a9054dc291b22678107e3257be5d7a711bdf0d826dc1d444e28d726282fa6306abf336f675e3794df
|
data/.rubocop.yml
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
inherit_mode:
|
2
|
+
merge:
|
3
|
+
- AllowedNames
|
4
|
+
|
1
5
|
AllCops:
|
2
6
|
TargetRubyVersion: 2.3
|
3
7
|
DisabledByDefault: true
|
@@ -24,6 +28,10 @@ Metrics/LineLength:
|
|
24
28
|
Naming:
|
25
29
|
Enabled: true
|
26
30
|
|
31
|
+
Naming/UncommunicativeMethodParamName:
|
32
|
+
AllowedNames:
|
33
|
+
- rp
|
34
|
+
|
27
35
|
Security:
|
28
36
|
Enabled: true
|
29
37
|
|
data/.travis.yml
CHANGED
@@ -5,12 +5,14 @@ cache: bundler
|
|
5
5
|
rvm:
|
6
6
|
- ruby-head
|
7
7
|
- 2.7.0-preview1
|
8
|
-
- 2.6.
|
9
|
-
- 2.5.
|
10
|
-
- 2.4.
|
8
|
+
- 2.6.4
|
9
|
+
- 2.5.6
|
10
|
+
- 2.4.7
|
11
11
|
- 2.3.8
|
12
12
|
|
13
13
|
gemfile:
|
14
|
+
- gemfiles/cose_head.gemfile
|
15
|
+
- gemfiles/openssl_head.gemfile
|
14
16
|
- gemfiles/openssl_2_1.gemfile
|
15
17
|
- gemfiles/openssl_2_0.gemfile
|
16
18
|
|
@@ -19,6 +21,8 @@ matrix:
|
|
19
21
|
allow_failures:
|
20
22
|
- rvm: ruby-head
|
21
23
|
- rvm: 2.7.0-preview1
|
24
|
+
- gemfile: gemfiles/cose_head.gemfile
|
25
|
+
- gemfile: gemfiles/openssl_head.gemfile
|
22
26
|
|
23
27
|
before_install:
|
24
28
|
- wget http://archive.ubuntu.com/ubuntu/pool/universe/f/faketime/libfaketime_0.9.7-3_amd64.deb
|
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_1" do
|
4
12
|
gem "openssl", "~> 2.1.0"
|
5
13
|
end
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,56 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v2.0.0.beta1] - 2019-09-16
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Smarter new public API methods:
|
8
|
+
- `WebAuthn.generate_user_id`
|
9
|
+
- `WebAuthn::Credential.options_for_create`
|
10
|
+
- `WebAuthn::Credential.options_for_get`
|
11
|
+
- `WebAuthn::Credential.from_create`
|
12
|
+
- `WebAuthn::Credential.from_get`
|
13
|
+
- All the above automatically handle encoding/decoding for necessary values. The specific encoding scheme can
|
14
|
+
be set (or even turned off) in `WebAutnn.configuration.encoding=`. Defaults to `:base64url`.
|
15
|
+
- `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)
|
17
|
+
|
18
|
+
### Changed
|
19
|
+
|
20
|
+
- `WebAuthn::AuthenticatorAssertionResponse#verify` no longer accepts `allowed_credentials:` keyword argument.
|
21
|
+
Please replace with `public_key:` and `sign_count:` keyword arguments. If you're not performing sign count
|
22
|
+
verification, signal opt-out with `sign_count: false`.
|
23
|
+
|
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.
|
26
|
+
- `WebAuthn::FakeClient#create` and `WebAuthn::FakeClient#get` better fakes a real client by not padding the
|
27
|
+
returned base64url-encoded `id` value.
|
28
|
+
|
29
|
+
### Deprecated
|
30
|
+
|
31
|
+
- `WebAuthn.credential_creation_options` method. Please consider using `WebAuthn::Credential.options_for_create`.
|
32
|
+
- `WebAuthn.credential_request_options` method. Please consider using `WebAuthn::Credential.options_for_get`.
|
33
|
+
|
34
|
+
### Removed
|
35
|
+
|
36
|
+
- `WebAuthn::AuthenticatorAssertionResponse.new` no longer accepts `credential_id`. No replacement needed, just don't
|
37
|
+
pass it.
|
38
|
+
|
39
|
+
### BREAKING CHANGES
|
40
|
+
|
41
|
+
- `WebAuthn::AuthenticatorAssertionResponse.new` no longer accepts `credential_id`. No replacement needed, just don't
|
42
|
+
pass it.
|
43
|
+
|
44
|
+
- `WebAuthn::AuthenticatorAssertionResponse#verify` no longer accepts `allowed_credentials:` keyword argument.
|
45
|
+
Please replace with `public_key:` and `sign_count:` keyword arguments. If you're not performing sign count
|
46
|
+
verification, signal opt-out with `sign_count: false`.
|
47
|
+
|
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.
|
50
|
+
|
51
|
+
- `WebAuthn::FakeClient#create` and `WebAuthn::FakeClient#get` better fakes a real client by not padding the
|
52
|
+
returned base64url-encoded `id` value.
|
53
|
+
|
3
54
|
## [v1.18.0] - 2019-07-27
|
4
55
|
|
5
56
|
### Added
|
@@ -209,6 +260,7 @@ Note: Both additions should help making it compatible with Chrome for Android 70
|
|
209
260
|
- `WebAuthn::AuthenticatorAttestationResponse.valid?` can be used to validate fido-u2f attestations returned by the browser
|
210
261
|
- Works with ruby 2.5
|
211
262
|
|
263
|
+
[v2.0.0.beta1]: https://github.com/cedarcode/webauthn-ruby/compare/v1.18.0...v2.0.0.beta1/
|
212
264
|
[v1.18.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.17.0...v1.18.0/
|
213
265
|
[v1.17.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.16.0...v1.17.0/
|
214
266
|
[v1.16.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.15.0...v1.16.0/
|
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
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.
|
3
|
+
|
1
4
|
# webauthn-ruby
|
2
5
|
|
3
|
-
![banner](webauthn-ruby.png)
|
6
|
+
![banner](assets/webauthn-ruby.png)
|
4
7
|
|
5
8
|
[![Gem](https://img.shields.io/gem/v/webauthn.svg?style=flat-square)](https://rubygems.org/gems/webauthn)
|
6
9
|
[![Travis](https://img.shields.io/travis/cedarcode/webauthn-ruby/master.svg?style=flat-square)](https://travis-ci.org/cedarcode/webauthn-ruby)
|
@@ -30,7 +33,9 @@ a user [credential](https://www.w3.org/TR/webauthn/#public-key-credential), incl
|
|
30
33
|
|
31
34
|
## Security
|
32
35
|
|
33
|
-
|
36
|
+
Please report security vulnerabilities to security@cedarcode.com.
|
37
|
+
|
38
|
+
_More_: [SECURITY](SECURITY.md)
|
34
39
|
|
35
40
|
## Background
|
36
41
|
|
@@ -117,126 +122,129 @@ WebAuthn.configure do |config|
|
|
117
122
|
# the suffix "example.com"
|
118
123
|
#
|
119
124
|
# config.rp_id = "example.com"
|
125
|
+
|
126
|
+
# Configure preferred binary-to-text encoding scheme. This should match the encoding scheme
|
127
|
+
# used in your client-side (user agent) code before sending the credential to the server.
|
128
|
+
# Supported values: `:base64url` (default), `:base64` or `false` to disable all encoding.
|
129
|
+
#
|
130
|
+
# config.encoding = false
|
120
131
|
end
|
121
132
|
```
|
122
133
|
|
123
|
-
### Registration
|
134
|
+
### Credential Registration
|
135
|
+
|
136
|
+
> The ceremony where a user, a Relying Party, and the user’s client (containing at least one authenticator) work in concert to create a public key credential and associate it with the user’s Relying Party account. Note that this includes employing a test of user presence or user verification.
|
137
|
+
> [[source](https://www.w3.org/TR/webauthn-2/#registration-ceremony)]
|
124
138
|
|
125
139
|
#### Initiation phase
|
126
140
|
|
127
141
|
```ruby
|
128
|
-
|
142
|
+
# Generate and store the WebAuthn User ID the first time the user registers a credential
|
143
|
+
if !user.webauthn_id
|
144
|
+
user.update!(webauthn_id: WebAuthn.generate_user_id)
|
145
|
+
end
|
146
|
+
|
147
|
+
options = WebAuthn::Credential.options_for_create(
|
148
|
+
user: { id: user.webauthn_id, name: user.name }
|
149
|
+
exclude: user.credentials.map { |c| c.webauthn_id }
|
150
|
+
)
|
129
151
|
|
130
152
|
# Store the newly generated challenge somewhere so you can have it
|
131
153
|
# for the verification phase.
|
154
|
+
session[:creation_challenge] = options.challenge
|
155
|
+
|
156
|
+
# Send `options` back to the browser, so that they can be used
|
157
|
+
# to call `navigator.credentials.create({ "publicKey": options })`
|
132
158
|
#
|
133
|
-
# You can
|
134
|
-
credential_creation_options[:challenge]
|
159
|
+
# You can call `options.as_json` to get a ruby hash with a JSON representation if needed.
|
135
160
|
|
136
|
-
#
|
137
|
-
#
|
161
|
+
# If inside a Rails controller, `render json: options` will just work.
|
162
|
+
# I.e. it will encode and convert the options to JSON automatically.
|
163
|
+
|
164
|
+
# For your frontend code, you might find @github/webauthn-json npm package useful.
|
165
|
+
# Especially for handling the necessary decoding of the options, and sending the
|
166
|
+
# `PublicKeyCredential` object back to the server.
|
138
167
|
```
|
139
168
|
|
140
169
|
#### Verification phase
|
141
170
|
|
142
171
|
```ruby
|
143
|
-
#
|
144
|
-
#
|
145
|
-
|
146
|
-
# `navigator.credentials.create` returned through the wire.
|
147
|
-
#
|
148
|
-
# Then you need to decode that data before passing it to the `#verify` method.
|
149
|
-
#
|
150
|
-
# E.g. in https://github.com/cedarcode/webauthn-rails-demo-app we use `Base64.strict_decode64`
|
151
|
-
# on the user-agent encoded data before calling `#verify`
|
152
|
-
attestation_object = "..."
|
153
|
-
client_data_json = "..."
|
154
|
-
|
155
|
-
attestation_response = WebAuthn::AuthenticatorAttestationResponse.new(
|
156
|
-
attestation_object: attestation_object,
|
157
|
-
client_data_json: client_data_json
|
158
|
-
)
|
159
|
-
|
172
|
+
# Assuming you're using @github/webauthn-json package to send the `PublicKeyCredential` object back
|
173
|
+
# in params[:publicKeyCredential]:
|
174
|
+
webauthn_credential = WebAuthn::Credential.from_create(params[:publicKeyCredential])
|
160
175
|
|
161
176
|
begin
|
162
|
-
|
163
|
-
|
164
|
-
#
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
rescue WebAuthn::VerificationError => e
|
177
|
+
webauthn_credential.verify(session[:creation_challenge])
|
178
|
+
|
179
|
+
# Store Credential ID, Credential Public Key and Sign Count for future authentications
|
180
|
+
user.credentials.create!(
|
181
|
+
webauthn_id: webauthn_credential.id,
|
182
|
+
public_key: webauthn_credential.public_key,
|
183
|
+
sign_count: webauthn_credential.sign_count
|
184
|
+
)
|
185
|
+
rescue WebAuthn::Error => e
|
172
186
|
# Handle error
|
173
187
|
end
|
174
188
|
```
|
175
189
|
|
176
|
-
### Authentication
|
190
|
+
### Credential Authentication
|
177
191
|
|
178
|
-
|
192
|
+
> The ceremony where a user, and the user’s client (containing at least one authenticator) work in concert to cryptographically prove to a Relying Party that the user controls the credential private key associated with a previously-registered public key credential (see Registration). Note that this includes a test of user presence or user verification. [[source](https://www.w3.org/TR/webauthn-2/#authentication-ceremony)]
|
179
193
|
|
180
|
-
|
194
|
+
#### Initiation phase
|
181
195
|
|
182
196
|
```ruby
|
183
|
-
|
184
|
-
credential_request_options[:allowCredentials] << { id: credential_id, type: "public-key" }
|
197
|
+
options = WebAuthn::Credential.options_for_get(allow: user.credentials.map { |c| c.webauthn_id })
|
185
198
|
|
186
199
|
# Store the newly generated challenge somewhere so you can have it
|
187
200
|
# for the verification phase.
|
188
|
-
|
189
|
-
|
190
|
-
|
201
|
+
session[:authentication_challenge] = options.challenge
|
202
|
+
|
203
|
+
# Send `options` back to the browser, so that they can be used
|
204
|
+
# to call `navigator.credentials.get({ "publicKey": options })`
|
205
|
+
|
206
|
+
# You can call `options.as_json` to get a ruby hash with a JSON representation if needed.
|
207
|
+
|
208
|
+
# If inside a Rails controller, `render json: options` will just work.
|
209
|
+
# I.e. it will encode and convert the options to JSON automatically.
|
191
210
|
|
192
|
-
#
|
193
|
-
#
|
211
|
+
# For your frontend code, you might find @github/webauthn-json npm package useful.
|
212
|
+
# Especially for handling the necessary decoding of the options, and sending the
|
213
|
+
# `PublicKeyCredential` object back to the server.
|
194
214
|
```
|
195
215
|
|
196
216
|
#### Verification phase
|
197
217
|
|
198
|
-
|
218
|
+
You need to look up the stored credential for a user by matching the `id` attribute from the PublicKeyCredential
|
219
|
+
interface returned by the browser to the stored `credential_id`. The corresponding `public_key` and `sign_count`
|
220
|
+
attributes must be passed as keyword arguments to the `verify` method call.
|
199
221
|
|
200
222
|
```ruby
|
201
|
-
#
|
202
|
-
#
|
203
|
-
|
204
|
-
# `navigator.credentials.get` returned through the wire.
|
205
|
-
#
|
206
|
-
# Then you need to decode that data before passing it to the `#verify` method.
|
207
|
-
#
|
208
|
-
# E.g. in https://github.com/cedarcode/webauthn-rails-demo-app we use `Base64.strict_decode64`
|
209
|
-
# on the user-agent encoded data before calling `#verify`
|
210
|
-
selected_credential_id = "..."
|
211
|
-
authenticator_data = "..."
|
212
|
-
client_data_json = "..."
|
213
|
-
signature = "..."
|
214
|
-
|
215
|
-
assertion_response = WebAuthn::AuthenticatorAssertionResponse.new(
|
216
|
-
credential_id: selected_credential_id,
|
217
|
-
authenticator_data: authenticator_data,
|
218
|
-
client_data_json: client_data_json,
|
219
|
-
signature: signature
|
220
|
-
)
|
223
|
+
# Assuming you're using @github/webauthn-json package to send the `PublicKeyCredential` object back
|
224
|
+
# in params[:publicKeyCredential]:
|
225
|
+
webauthn_credential = WebAuthn::Credential.from_get(params[:publicKeyCredential])
|
221
226
|
|
222
|
-
|
223
|
-
# previously stored credential for the user that is attempting to sign in.
|
224
|
-
allowed_credential = {
|
225
|
-
id: credential_id,
|
226
|
-
public_key: credential_public_key,
|
227
|
-
sign_count: sign_count,
|
228
|
-
}
|
227
|
+
stored_credential = user.credentials.find_by(webauthn_id: webauthn_credential.id)
|
229
228
|
|
230
229
|
begin
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
230
|
+
webauthn_credential.verify(
|
231
|
+
session[:authentication_challenge],
|
232
|
+
public_key: stored_credential.public_key,
|
233
|
+
sign_count: stored_credential.sign_count
|
234
|
+
)
|
235
|
+
|
236
|
+
# Update the stored credential sign count with the value from `webauthn_credential.sign_count`
|
237
|
+
stored_credential.update!(sign_count: webauthn_credential.sign_count)
|
238
|
+
|
239
|
+
# Continue with successful sign in or 2FA verification...
|
240
|
+
|
241
|
+
rescue WebAuthn::SignCountVerificationError => e
|
242
|
+
# Cryptographic verification of the authenticator data succeeded, but the signature counter was less then or equal
|
243
|
+
# to the stored value. This can have several reasons and depending on your risk tolerance you can choose to fail or
|
244
|
+
# pass authentication. For more information see https://www.w3.org/TR/webauthn/#sign-counter
|
245
|
+
rescue WebAuthn::Error => e
|
235
246
|
# Handle error
|
236
247
|
end
|
237
|
-
|
238
|
-
# Find the selected credential in your data storage using `selected_credential_id`
|
239
|
-
# Update the stored sign count with the value from `assertion_response.authenticator_data.sign_count`
|
240
248
|
```
|
241
249
|
|
242
250
|
## API
|
data/SECURITY.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Security Policy
|
2
|
+
|
3
|
+
## Supported Versions
|
4
|
+
|
5
|
+
| Version | Supported |
|
6
|
+
| ------- | ------------------ |
|
7
|
+
| 1.18.z | :white_check_mark: |
|
8
|
+
| 1.17.z | :white_check_mark: |
|
9
|
+
| 1.16.z | :white_check_mark: |
|
10
|
+
| 1.15.z | :white_check_mark: |
|
11
|
+
| < 1.15 | :x: |
|
12
|
+
|
13
|
+
## Reporting a Vulnerability
|
14
|
+
|
15
|
+
If you have discovered a security bug, please send an email to security@cedarcode.com
|
16
|
+
instead of posting to the GitHub issue tracker.
|
17
|
+
|
18
|
+
Thank you!
|
data/lib/webauthn.rb
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "webauthn/configuration"
|
4
|
+
require "webauthn/credential"
|
4
5
|
require "webauthn/credential_creation_options"
|
5
6
|
require "webauthn/credential_request_options"
|
6
|
-
require "webauthn/public_key_credential"
|
7
7
|
require "webauthn/version"
|
8
|
+
|
9
|
+
module WebAuthn
|
10
|
+
TYPE_PUBLIC_KEY = "public-key"
|
11
|
+
|
12
|
+
def self.generate_user_id
|
13
|
+
configuration.encoder.encode(SecureRandom.random_bytes(64))
|
14
|
+
end
|
15
|
+
end
|
@@ -20,6 +20,10 @@ module WebAuthn
|
|
20
20
|
[WebAuthn::AttestationStatement::ATTESTATION_TYPE_BASIC, attestation_certificate]
|
21
21
|
end
|
22
22
|
|
23
|
+
def attestation_certificate
|
24
|
+
attestation_response.certificate_chain[0]
|
25
|
+
end
|
26
|
+
|
23
27
|
private
|
24
28
|
|
25
29
|
# FIXME: This should be a responsibility of AndroidSafetynet::AttestationResponse#verify
|
@@ -46,10 +50,6 @@ module WebAuthn
|
|
46
50
|
attestation_response.cts_profile_match?
|
47
51
|
end
|
48
52
|
|
49
|
-
def attestation_certificate
|
50
|
-
attestation_response.certificate_chain[0]
|
51
|
-
end
|
52
|
-
|
53
53
|
def signing_certificates
|
54
54
|
attestation_response.certificate_chain[1..-1]
|
55
55
|
end
|
@@ -26,6 +26,10 @@ module WebAuthn
|
|
26
26
|
raise NotImpelementedError
|
27
27
|
end
|
28
28
|
|
29
|
+
def attestation_certificate
|
30
|
+
attestation_certificate_chain&.first
|
31
|
+
end
|
32
|
+
|
29
33
|
private
|
30
34
|
|
31
35
|
attr_reader :statement
|
@@ -42,10 +46,6 @@ module WebAuthn
|
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
45
|
-
def attestation_certificate
|
46
|
-
attestation_certificate_chain&.first
|
47
|
-
end
|
48
|
-
|
49
49
|
def attestation_certificate_chain
|
50
50
|
@attestation_certificate_chain ||= raw_attestation_certificates&.map do |raw_certificate|
|
51
51
|
OpenSSL::X509::Certificate.new(raw_certificate)
|