webauthn 3.0.0.alpha2 → 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.
- 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:
|