webauthn 3.0.0.alpha2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +2 -1
- data/.github/workflows/git.yml +1 -1
- data/CHANGELOG.md +9 -0
- data/README.md +3 -3
- data/docs/advanced_configuration.md +2 -2
- data/docs/u2f_migration.md +14 -21
- data/lib/webauthn/authenticator_data.rb +10 -2
- data/lib/webauthn/configuration.rb +3 -1
- data/lib/webauthn/fake_authenticator/attestation_object.rb +8 -0
- data/lib/webauthn/fake_authenticator/authenticator_data.rb +19 -4
- data/lib/webauthn/fake_authenticator.rb +8 -0
- data/lib/webauthn/fake_client.rb +8 -0
- data/lib/webauthn/public_key_credential/options.rb +5 -1
- data/lib/webauthn/public_key_credential/request_options.rb +10 -0
- data/lib/webauthn/public_key_credential.rb +16 -4
- data/lib/webauthn/public_key_credential_with_assertion.rb +14 -1
- data/lib/webauthn/relying_party.rb +5 -2
- data/lib/webauthn/version.rb +1 -1
- data/webauthn.gemspec +2 -2
- metadata +6 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b133f46bd003c9bfb9a8557bb8caeca7239fcd6c185f78e74e0ae578444d576e
|
4
|
+
data.tar.gz: 14a32debc72ddcfe7e752118ebd4db832b8a46a5628ee54830f30eada4159bcf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b4ff5cee18575b517473fef7d8000d7e41f113b178378e64a4d2b9036d248f4295edd846a519ab76036a270c3066020fbe44847019812c2a5758f2b1b428f4c
|
7
|
+
data.tar.gz: f3ab22709cbf537982e163acc60dbe114217f223b18cb4cf681a3d932e2f31276f8286091e49da392356c1958ada7e2c07a5b86b48d57b597f965a57c1bcf63d
|
data/.github/workflows/build.yml
CHANGED
@@ -16,6 +16,7 @@ jobs:
|
|
16
16
|
fail-fast: false
|
17
17
|
matrix:
|
18
18
|
ruby:
|
19
|
+
- '3.2'
|
19
20
|
- '3.1'
|
20
21
|
- '3.0'
|
21
22
|
- '2.7'
|
@@ -23,7 +24,7 @@ jobs:
|
|
23
24
|
- '2.5'
|
24
25
|
- truffleruby
|
25
26
|
steps:
|
26
|
-
- uses: actions/checkout@
|
27
|
+
- uses: actions/checkout@v3
|
27
28
|
- uses: ruby/setup-ruby@v1
|
28
29
|
with:
|
29
30
|
ruby-version: ${{ matrix.ruby }}
|
data/.github/workflows/git.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v3.0.0] - 2023-02-15
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Add the capability of handling appid extension #319 [@santiagorodriguez96]
|
8
|
+
- Add support for credential backup flags #378 [@santiagorodriguez96]
|
9
|
+
- Update dependencies to make gem compatible with OpenSSL 3.1 ([@bdewater],[@santiagorodriguez96])
|
10
|
+
|
3
11
|
## [v3.0.0.alpha2] - 2022-09-12
|
4
12
|
|
5
13
|
### Added
|
@@ -350,6 +358,7 @@ Note: Both additions should help making it compatible with Chrome for Android 70
|
|
350
358
|
- `WebAuthn::AuthenticatorAttestationResponse.valid?` can be used to validate fido-u2f attestations returned by the browser
|
351
359
|
- Works with ruby 2.5
|
352
360
|
|
361
|
+
[v3.0.0]: https://github.com/cedarcode/webauthn-ruby/compare/2-stable...v3.0.0/
|
353
362
|
[v3.0.0.alpha2]: https://github.com/cedarcode/webauthn-ruby/compare/2-stable...v3.0.0.alpha2/
|
354
363
|
[v3.0.0.alpha1]: https://github.com/cedarcode/webauthn-ruby/compare/v2.3.0...v3.0.0.alpha1
|
355
364
|
[v2.5.2]: https://github.com/cedarcode/webauthn-ruby/compare/v2.5.1...v2.5.2/
|
data/README.md
CHANGED
@@ -16,7 +16,7 @@ Makes your Ruby/Rails web server become a functional [WebAuthn Relying Party](ht
|
|
16
16
|
|
17
17
|
Takes care of the [server-side operations](https://www.w3.org/TR/webauthn/#rp-operations) needed to
|
18
18
|
[register](https://www.w3.org/TR/webauthn/#registration) or [authenticate](https://www.w3.org/TR/webauthn/#authentication)
|
19
|
-
a user [credential](https://www.w3.org/TR/webauthn/#public-key-credential), including the necessary cryptographic checks.
|
19
|
+
a user's [public key credential](https://www.w3.org/TR/webauthn/#public-key-credential) (also called a "passkey"), including the necessary cryptographic checks.
|
20
20
|
|
21
21
|
## Table of Contents
|
22
22
|
|
@@ -52,7 +52,7 @@ WebAuthn (Web Authentication) is a W3C standard for secure public-key authentica
|
|
52
52
|
|
53
53
|
- WebAuthn [W3C Recommendation](https://www.w3.org/TR/webauthn/) (i.e. "The Standard")
|
54
54
|
- [Web Authentication API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API) in MDN
|
55
|
-
- How to use
|
55
|
+
- How to use WebAuthn in native [Android](https://developers.google.com/identity/fido/android/native-apps) or [macOS/iOS/iPadOS](https://developer.apple.com/documentation/authenticationservices/public-private_key_authentication) apps.
|
56
56
|
- [Security Benefits for WebAuthn Servers (a.k.a Relying Parties)](https://www.w3.org/TR/webauthn/#sctn-rp-benefits)
|
57
57
|
|
58
58
|
## Prerequisites
|
@@ -89,7 +89,7 @@ Or install it yourself as:
|
|
89
89
|
|
90
90
|
## Usage
|
91
91
|
|
92
|
-
You can find a working example on how to use this gem in a __Rails__ app in [webauthn-rails-demo-app](https://github.com/cedarcode/webauthn-rails-demo-app).
|
92
|
+
You can find a working example on how to use this gem in a pasword-less login in a __Rails__ app in [webauthn-rails-demo-app](https://github.com/cedarcode/webauthn-rails-demo-app). If you want to see an example on how to use this gem as a second factor authenticator in a __Rails__ application instead, you can check it in [webauthn-2fa-rails-demo](https://github.com/cedarcode/webauthn-2fa-rails-demo).
|
93
93
|
|
94
94
|
If you are migrating an existing application from the legacy FIDO U2F JavaScript API to WebAuthn, also refer to
|
95
95
|
[`docs/u2f_migration.md`](docs/u2f_migration.md).
|
@@ -21,7 +21,7 @@ Intead of the [Global Configuration](../README.md#configuration) you place in `c
|
|
21
21
|
relying_party = WebAuthn::RelyingParty.new(
|
22
22
|
# This value needs to match `window.location.origin` evaluated by
|
23
23
|
# the User Agent during registration and authentication ceremonies.
|
24
|
-
origin: "https://admin.example.com"
|
24
|
+
origin: "https://admin.example.com",
|
25
25
|
|
26
26
|
# Relying Party name for display purposes
|
27
27
|
name: "Admin Site for Example Inc."
|
@@ -71,7 +71,7 @@ if !user.webauthn_id
|
|
71
71
|
user.update!(webauthn_id: WebAuthn.generate_user_id)
|
72
72
|
end
|
73
73
|
|
74
|
-
options = relying_party.
|
74
|
+
options = relying_party.options_for_registration(
|
75
75
|
user: { id: user.webauthn_id, name: user.name },
|
76
76
|
exclude: user.credentials.map { |c| c.webauthn_id }
|
77
77
|
)
|
data/docs/u2f_migration.md
CHANGED
@@ -53,7 +53,7 @@ migrated_credential.authenticator_data.sign_count
|
|
53
53
|
|
54
54
|
## Authenticate migrated U2F credentials
|
55
55
|
|
56
|
-
Following the documentation on the [authentication initiation](https://github.com/cedarcode/webauthn-ruby/blob/master/README.md#
|
56
|
+
Following the documentation on the [authentication initiation](https://github.com/cedarcode/webauthn-ruby/blob/master/README.md#initiation-phase-1),
|
57
57
|
you need to specify the [FIDO AppID extension](https://www.w3.org/TR/webauthn/#sctn-appid-extension) for U2F migratedq
|
58
58
|
credentials. The WebAuthn standard explains:
|
59
59
|
|
@@ -65,33 +65,26 @@ For the earlier given example `domain` this means:
|
|
65
65
|
- FIDO AppID: `https://login.example.com`
|
66
66
|
- Valid RP IDs: `login.example.com` (default) and `example.com`
|
67
67
|
|
68
|
+
You can request the use of the `appid` extension by setting the AppID in the configuration, like this:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
WebAuthn.configure do |config|
|
72
|
+
config.legacy_u2f_appid = "https://login.example.com"
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
By doing this, the `appid` extension will be automatically requested when generating the options for get:
|
77
|
+
|
68
78
|
```ruby
|
69
|
-
|
70
|
-
credential_request_options[:extensions] = { appid: domain.to_s }
|
79
|
+
options = WebAuthn::Credential.options_for_get
|
71
80
|
```
|
72
81
|
|
73
82
|
On the frontend, in the resolved value from `navigator.credentials.get({ "publicKey": credentialRequestOptions })` add
|
74
83
|
a call to [getClientExtensionResults()](https://www.w3.org/TR/webauthn/#dom-publickeycredential-getclientextensionresults)
|
75
84
|
and send its result to your backend alongside the `id`/`rawId` and `response` values. If the authenticator used the AppID
|
76
|
-
extension, the returned value will contain `{ "appid": true }`.
|
85
|
+
extension, the returned value will contain `{ "appid": true }`.
|
77
86
|
|
78
|
-
During authentication verification phase, you
|
87
|
+
During authentication verification phase, if you followed the [verification phase documentation](https://github.com/cedarcode/webauthn-ruby#verification-phase-1) and have set the AppID in the config, the method `PublicKeyCredentialWithAssertion#verify` will be smart enough to determine if it should use the AppID or the RP ID to verify the WebAuthn credential, depending on the output of the `appid` client extension:
|
79
88
|
|
80
89
|
> If true, the AppID was used and thus, when verifying an assertion, the Relying Party MUST expect the `rpIdHash` to be
|
81
90
|
> the hash of the _AppID_, not the RP ID.
|
82
|
-
|
83
|
-
```ruby
|
84
|
-
assertion_response = WebAuthn::AuthenticatorAssertionResponse.new(
|
85
|
-
user_handle: params[:response][:userHandle],
|
86
|
-
authenticator_data: params[:response][:authenticatorData],
|
87
|
-
client_data_json: params[:response][:clientDataJSON],
|
88
|
-
signature: params[:response][:signature],
|
89
|
-
)
|
90
|
-
|
91
|
-
assertion_response.verify(
|
92
|
-
expected_challenge,
|
93
|
-
public_key: credential.public_key,
|
94
|
-
sign_count: credential.count,
|
95
|
-
rp_id: params[:clientExtensionResults][:appid] ? domain.to_s : domain.host,
|
96
|
-
)
|
97
|
-
```
|
@@ -19,9 +19,9 @@ module WebAuthn
|
|
19
19
|
struct :flags do
|
20
20
|
bit1 :extension_data_included
|
21
21
|
bit1 :attested_credential_data_included
|
22
|
-
bit1 :reserved_for_future_use_4
|
23
|
-
bit1 :reserved_for_future_use_3
|
24
22
|
bit1 :reserved_for_future_use_2
|
23
|
+
bit1 :backup_state
|
24
|
+
bit1 :backup_eligibility
|
25
25
|
bit1 :user_verified
|
26
26
|
bit1 :reserved_for_future_use_1
|
27
27
|
bit1 :user_present
|
@@ -58,6 +58,14 @@ module WebAuthn
|
|
58
58
|
flags.user_verified == 1
|
59
59
|
end
|
60
60
|
|
61
|
+
def credential_backup_eligible?
|
62
|
+
flags.backup_eligibility == 1
|
63
|
+
end
|
64
|
+
|
65
|
+
def credential_backed_up?
|
66
|
+
flags.backup_state == 1
|
67
|
+
end
|
68
|
+
|
61
69
|
def attested_credential_data_included?
|
62
70
|
flags.attested_credential_data_included == 1
|
63
71
|
end
|
@@ -13,6 +13,8 @@ module WebAuthn
|
|
13
13
|
credential_key:,
|
14
14
|
user_present: true,
|
15
15
|
user_verified: false,
|
16
|
+
backup_eligibility: false,
|
17
|
+
backup_state: false,
|
16
18
|
attested_credential_data: true,
|
17
19
|
sign_count: 0,
|
18
20
|
extensions: nil
|
@@ -23,6 +25,8 @@ module WebAuthn
|
|
23
25
|
@credential_key = credential_key
|
24
26
|
@user_present = user_present
|
25
27
|
@user_verified = user_verified
|
28
|
+
@backup_eligibility = backup_eligibility
|
29
|
+
@backup_state = backup_state
|
26
30
|
@attested_credential_data = attested_credential_data
|
27
31
|
@sign_count = sign_count
|
28
32
|
@extensions = extensions
|
@@ -45,6 +49,8 @@ module WebAuthn
|
|
45
49
|
:credential_key,
|
46
50
|
:user_present,
|
47
51
|
:user_verified,
|
52
|
+
:backup_eligibility,
|
53
|
+
:backup_state,
|
48
54
|
:attested_credential_data,
|
49
55
|
:sign_count,
|
50
56
|
:extensions
|
@@ -63,6 +69,8 @@ module WebAuthn
|
|
63
69
|
credential: credential_data,
|
64
70
|
user_present: user_present,
|
65
71
|
user_verified: user_verified,
|
72
|
+
backup_eligibility: backup_eligibility,
|
73
|
+
backup_state: backup_state,
|
66
74
|
sign_count: 0,
|
67
75
|
extensions: extensions
|
68
76
|
)
|
@@ -20,6 +20,8 @@ module WebAuthn
|
|
20
20
|
sign_count: 0,
|
21
21
|
user_present: true,
|
22
22
|
user_verified: !user_present,
|
23
|
+
backup_eligibility: false,
|
24
|
+
backup_state: false,
|
23
25
|
aaguid: AAGUID,
|
24
26
|
extensions: { "fakeExtension" => "fakeExtensionValue" }
|
25
27
|
)
|
@@ -28,6 +30,8 @@ module WebAuthn
|
|
28
30
|
@sign_count = sign_count
|
29
31
|
@user_present = user_present
|
30
32
|
@user_verified = user_verified
|
33
|
+
@backup_eligibility = backup_eligibility
|
34
|
+
@backup_state = backup_state
|
31
35
|
@aaguid = aaguid
|
32
36
|
@extensions = extensions
|
33
37
|
end
|
@@ -38,7 +42,13 @@ module WebAuthn
|
|
38
42
|
|
39
43
|
private
|
40
44
|
|
41
|
-
attr_reader :rp_id_hash,
|
45
|
+
attr_reader :rp_id_hash,
|
46
|
+
:credential,
|
47
|
+
:user_present,
|
48
|
+
:user_verified,
|
49
|
+
:extensions,
|
50
|
+
:backup_eligibility,
|
51
|
+
:backup_state
|
42
52
|
|
43
53
|
def flags
|
44
54
|
[
|
@@ -46,8 +56,8 @@ module WebAuthn
|
|
46
56
|
bit(:user_present),
|
47
57
|
reserved_for_future_use_bit,
|
48
58
|
bit(:user_verified),
|
49
|
-
|
50
|
-
|
59
|
+
bit(:backup_eligibility),
|
60
|
+
bit(:backup_state),
|
51
61
|
reserved_for_future_use_bit,
|
52
62
|
attested_credential_data_included_bit,
|
53
63
|
extension_data_included_bit
|
@@ -108,7 +118,12 @@ module WebAuthn
|
|
108
118
|
end
|
109
119
|
|
110
120
|
def context
|
111
|
-
{
|
121
|
+
{
|
122
|
+
user_present: user_present,
|
123
|
+
user_verified: user_verified,
|
124
|
+
backup_eligibility: backup_eligibility,
|
125
|
+
backup_state: backup_state
|
126
|
+
}
|
112
127
|
end
|
113
128
|
|
114
129
|
def cose_credential_public_key
|
@@ -17,6 +17,8 @@ module WebAuthn
|
|
17
17
|
client_data_hash:,
|
18
18
|
user_present: true,
|
19
19
|
user_verified: false,
|
20
|
+
backup_eligibility: false,
|
21
|
+
backup_state: false,
|
20
22
|
attested_credential_data: true,
|
21
23
|
sign_count: nil,
|
22
24
|
extensions: nil
|
@@ -37,6 +39,8 @@ module WebAuthn
|
|
37
39
|
credential_key: credential_key,
|
38
40
|
user_present: user_present,
|
39
41
|
user_verified: user_verified,
|
42
|
+
backup_eligibility: backup_eligibility,
|
43
|
+
backup_state: backup_state,
|
40
44
|
attested_credential_data: attested_credential_data,
|
41
45
|
sign_count: sign_count,
|
42
46
|
extensions: extensions
|
@@ -48,6 +52,8 @@ module WebAuthn
|
|
48
52
|
client_data_hash:,
|
49
53
|
user_present: true,
|
50
54
|
user_verified: false,
|
55
|
+
backup_eligibility: false,
|
56
|
+
backup_state: false,
|
51
57
|
aaguid: AuthenticatorData::AAGUID,
|
52
58
|
sign_count: nil,
|
53
59
|
extensions: nil,
|
@@ -71,6 +77,8 @@ module WebAuthn
|
|
71
77
|
rp_id_hash: hashed(rp_id),
|
72
78
|
user_present: user_present,
|
73
79
|
user_verified: user_verified,
|
80
|
+
backup_eligibility: backup_eligibility,
|
81
|
+
backup_state: backup_state,
|
74
82
|
aaguid: aaguid,
|
75
83
|
credential: nil,
|
76
84
|
sign_count: sign_count || credential_sign_count,
|
data/lib/webauthn/fake_client.rb
CHANGED
@@ -29,6 +29,8 @@ module WebAuthn
|
|
29
29
|
rp_id: nil,
|
30
30
|
user_present: true,
|
31
31
|
user_verified: false,
|
32
|
+
backup_eligibility: false,
|
33
|
+
backup_state: false,
|
32
34
|
attested_credential_data: true,
|
33
35
|
extensions: nil
|
34
36
|
)
|
@@ -42,6 +44,8 @@ module WebAuthn
|
|
42
44
|
client_data_hash: client_data_hash,
|
43
45
|
user_present: user_present,
|
44
46
|
user_verified: user_verified,
|
47
|
+
backup_eligibility: backup_eligibility,
|
48
|
+
backup_state: backup_state,
|
45
49
|
attested_credential_data: attested_credential_data,
|
46
50
|
extensions: extensions
|
47
51
|
)
|
@@ -72,6 +76,8 @@ module WebAuthn
|
|
72
76
|
rp_id: nil,
|
73
77
|
user_present: true,
|
74
78
|
user_verified: false,
|
79
|
+
backup_eligibility: false,
|
80
|
+
backup_state: true,
|
75
81
|
sign_count: nil,
|
76
82
|
extensions: nil,
|
77
83
|
user_handle: nil,
|
@@ -90,6 +96,8 @@ module WebAuthn
|
|
90
96
|
client_data_hash: client_data_hash,
|
91
97
|
user_present: user_present,
|
92
98
|
user_verified: user_verified,
|
99
|
+
backup_eligibility: backup_eligibility,
|
100
|
+
backup_state: backup_state,
|
93
101
|
sign_count: sign_count,
|
94
102
|
extensions: extensions,
|
95
103
|
allow_credentials: allow_credentials
|
@@ -13,7 +13,7 @@ module WebAuthn
|
|
13
13
|
def initialize(timeout: nil, extensions: nil, relying_party: WebAuthn.configuration.relying_party)
|
14
14
|
@relying_party = relying_party
|
15
15
|
@timeout = timeout || default_timeout
|
16
|
-
@extensions = extensions
|
16
|
+
@extensions = default_extensions.merge(extensions || {})
|
17
17
|
end
|
18
18
|
|
19
19
|
def challenge
|
@@ -61,6 +61,10 @@ module WebAuthn
|
|
61
61
|
relying_party.credential_options_timeout
|
62
62
|
end
|
63
63
|
|
64
|
+
def default_extensions
|
65
|
+
{}
|
66
|
+
end
|
67
|
+
|
64
68
|
def as_public_key_descriptors(ids)
|
65
69
|
Array(ids).map { |id| { type: TYPE_PUBLIC_KEY, id: id } }
|
66
70
|
end
|
@@ -26,6 +26,16 @@ module WebAuthn
|
|
26
26
|
super.concat([:allow_credentials, :rp_id, :user_verification])
|
27
27
|
end
|
28
28
|
|
29
|
+
def default_extensions
|
30
|
+
extensions = super || {}
|
31
|
+
|
32
|
+
if relying_party.legacy_u2f_appid
|
33
|
+
extensions.merge!(appid: relying_party.legacy_u2f_appid)
|
34
|
+
end
|
35
|
+
|
36
|
+
extensions
|
37
|
+
end
|
38
|
+
|
29
39
|
def allow_credentials_from_allow
|
30
40
|
if allow
|
31
41
|
as_public_key_descriptors(allow)
|
@@ -13,7 +13,7 @@ module WebAuthn
|
|
13
13
|
raw_id: relying_party.encoder.decode(credential["rawId"]),
|
14
14
|
client_extension_outputs: credential["clientExtensionResults"],
|
15
15
|
response: response_class.from_client(credential["response"], relying_party: relying_party),
|
16
|
-
|
16
|
+
relying_party: relying_party
|
17
17
|
)
|
18
18
|
end
|
19
19
|
|
@@ -23,14 +23,14 @@ module WebAuthn
|
|
23
23
|
raw_id:,
|
24
24
|
response:,
|
25
25
|
client_extension_outputs: {},
|
26
|
-
|
26
|
+
relying_party: WebAuthn.configuration.relying_party
|
27
27
|
)
|
28
28
|
@type = type
|
29
29
|
@id = id
|
30
30
|
@raw_id = raw_id
|
31
31
|
@client_extension_outputs = client_extension_outputs
|
32
32
|
@response = response
|
33
|
-
@
|
33
|
+
@relying_party = relying_party
|
34
34
|
end
|
35
35
|
|
36
36
|
def verify(*_args)
|
@@ -48,9 +48,17 @@ module WebAuthn
|
|
48
48
|
authenticator_data.extension_data if authenticator_data&.extension_data_included?
|
49
49
|
end
|
50
50
|
|
51
|
+
def backup_eligible?
|
52
|
+
authenticator_data&.credential_backup_eligible?
|
53
|
+
end
|
54
|
+
|
55
|
+
def backed_up?
|
56
|
+
authenticator_data&.credential_backed_up?
|
57
|
+
end
|
58
|
+
|
51
59
|
private
|
52
60
|
|
53
|
-
attr_reader :
|
61
|
+
attr_reader :relying_party
|
54
62
|
|
55
63
|
def valid_type?
|
56
64
|
type == TYPE_PUBLIC_KEY
|
@@ -63,5 +71,9 @@ module WebAuthn
|
|
63
71
|
def authenticator_data
|
64
72
|
response&.authenticator_data
|
65
73
|
end
|
74
|
+
|
75
|
+
def encoder
|
76
|
+
relying_party.encoder
|
77
|
+
end
|
66
78
|
end
|
67
79
|
end
|
@@ -16,7 +16,8 @@ module WebAuthn
|
|
16
16
|
encoder.decode(challenge),
|
17
17
|
public_key: encoder.decode(public_key),
|
18
18
|
sign_count: sign_count,
|
19
|
-
user_verification: user_verification
|
19
|
+
user_verification: user_verification,
|
20
|
+
rp_id: appid_extension_output ? appid : nil
|
20
21
|
)
|
21
22
|
|
22
23
|
true
|
@@ -31,5 +32,17 @@ module WebAuthn
|
|
31
32
|
def raw_user_handle
|
32
33
|
response.user_handle
|
33
34
|
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def appid_extension_output
|
39
|
+
return if client_extension_outputs.nil?
|
40
|
+
|
41
|
+
client_extension_outputs['appid']
|
42
|
+
end
|
43
|
+
|
44
|
+
def appid
|
45
|
+
URI.parse(relying_party.legacy_u2f_appid || raise("Unspecified legacy U2F AppID")).to_s
|
46
|
+
end
|
34
47
|
end
|
35
48
|
end
|
@@ -25,7 +25,8 @@ module WebAuthn
|
|
25
25
|
credential_options_timeout: 120000,
|
26
26
|
silent_authentication: false,
|
27
27
|
acceptable_attestation_types: ['None', 'Self', 'Basic', 'AttCA', 'Basic_or_AttCA', 'AnonCA'],
|
28
|
-
attestation_root_certificates_finders: []
|
28
|
+
attestation_root_certificates_finders: [],
|
29
|
+
legacy_u2f_appid: nil
|
29
30
|
)
|
30
31
|
@algorithms = algorithms
|
31
32
|
@encoding = encoding
|
@@ -36,6 +37,7 @@ module WebAuthn
|
|
36
37
|
@credential_options_timeout = credential_options_timeout
|
37
38
|
@silent_authentication = silent_authentication
|
38
39
|
@acceptable_attestation_types = acceptable_attestation_types
|
40
|
+
@legacy_u2f_appid = legacy_u2f_appid
|
39
41
|
self.attestation_root_certificates_finders = attestation_root_certificates_finders
|
40
42
|
end
|
41
43
|
|
@@ -47,7 +49,8 @@ module WebAuthn
|
|
47
49
|
:verify_attestation_statement,
|
48
50
|
:credential_options_timeout,
|
49
51
|
:silent_authentication,
|
50
|
-
:acceptable_attestation_types
|
52
|
+
:acceptable_attestation_types,
|
53
|
+
:legacy_u2f_appid
|
51
54
|
|
52
55
|
attr_reader :attestation_root_certificates_finders
|
53
56
|
|
data/lib/webauthn/version.rb
CHANGED
data/webauthn.gemspec
CHANGED
@@ -38,9 +38,9 @@ Gem::Specification.new do |spec|
|
|
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.2"
|
41
|
+
spec.add_dependency "openssl", ">= 2.2"
|
42
42
|
spec.add_dependency "safety_net_attestation", "~> 0.4.0"
|
43
|
-
spec.add_dependency "tpm-key_attestation", "~> 0.
|
43
|
+
spec.add_dependency "tpm-key_attestation", "~> 0.12.0"
|
44
44
|
|
45
45
|
spec.add_development_dependency "bundler", ">= 1.17", "< 3.0"
|
46
46
|
spec.add_development_dependency "byebug", "~> 11.0"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webauthn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.0
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gonzalo Rodriguez
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
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
|
@@ -88,9 +88,6 @@ dependencies:
|
|
88
88
|
- - ">="
|
89
89
|
- !ruby/object:Gem::Version
|
90
90
|
version: '2.2'
|
91
|
-
- - "<"
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '3.1'
|
94
91
|
type: :runtime
|
95
92
|
prerelease: false
|
96
93
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -98,9 +95,6 @@ dependencies:
|
|
98
95
|
- - ">="
|
99
96
|
- !ruby/object:Gem::Version
|
100
97
|
version: '2.2'
|
101
|
-
- - "<"
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '3.1'
|
104
98
|
- !ruby/object:Gem::Dependency
|
105
99
|
name: safety_net_attestation
|
106
100
|
requirement: !ruby/object:Gem::Requirement
|
@@ -121,14 +115,14 @@ dependencies:
|
|
121
115
|
requirements:
|
122
116
|
- - "~>"
|
123
117
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0.
|
118
|
+
version: 0.12.0
|
125
119
|
type: :runtime
|
126
120
|
prerelease: false
|
127
121
|
version_requirements: !ruby/object:Gem::Requirement
|
128
122
|
requirements:
|
129
123
|
- - "~>"
|
130
124
|
- !ruby/object:Gem::Version
|
131
|
-
version: 0.
|
125
|
+
version: 0.12.0
|
132
126
|
- !ruby/object:Gem::Dependency
|
133
127
|
name: bundler
|
134
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -324,9 +318,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
324
318
|
version: '2.5'
|
325
319
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
326
320
|
requirements:
|
327
|
-
- - "
|
321
|
+
- - ">="
|
328
322
|
- !ruby/object:Gem::Version
|
329
|
-
version:
|
323
|
+
version: '0'
|
330
324
|
requirements: []
|
331
325
|
rubygems_version: 3.2.32
|
332
326
|
signing_key:
|