webauthn 1.14.0 → 1.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +37 -24
- data/lib/android_safetynet/attestation_response.rb +4 -13
- data/lib/webauthn.rb +3 -43
- data/lib/webauthn/attestation_statement.rb +0 -7
- data/lib/webauthn/attestation_statement/android_key.rb +1 -0
- data/lib/webauthn/attestation_statement/base.rb +8 -0
- data/lib/webauthn/attestation_statement/tpm/cert_info.rb +2 -0
- data/lib/webauthn/attestation_statement/tpm/pub_area.rb +3 -1
- data/lib/webauthn/authenticator_assertion_response.rb +2 -1
- data/lib/webauthn/authenticator_attestation_response.rb +1 -1
- data/lib/webauthn/authenticator_response.rb +10 -2
- data/lib/webauthn/client_data.rb +1 -0
- data/lib/webauthn/configuration.rb +17 -0
- data/lib/webauthn/credential_creation_options.rb +60 -0
- data/lib/webauthn/credential_entity.rb +11 -0
- data/lib/webauthn/credential_options.rb +13 -0
- data/lib/webauthn/credential_request_options.rb +19 -0
- data/lib/webauthn/credential_rp_entity.rb +8 -0
- data/lib/webauthn/credential_user_entity.rb +16 -0
- data/lib/webauthn/fake_authenticator.rb +7 -3
- data/lib/webauthn/fake_authenticator/authenticator_data.rb +6 -4
- data/lib/webauthn/fake_client.rb +1 -0
- data/lib/webauthn/signature_verifier.rb +3 -0
- data/lib/webauthn/version.rb +1 -1
- data/webauthn.gemspec +4 -3
- metadata +15 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac8a0cc80530217e636ae8c83128363f9f9e725243cb40f5dad4e0941db4149f
|
4
|
+
data.tar.gz: b781f8035cf6c25626b6da8e0ced92838d5d6f5defcecc7180f826af4184540d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '01449706124d9e42b81c4691075e1de5f6192651a9cb8f798c2b78bb31ef0171d9ece8ef09412b73cbdb3444f38e963455439a5d1cf9eb781c8804e713dd5002'
|
7
|
+
data.tar.gz: 4f5c370130707a529566f4be6887c592c600674caf5f2b198d9329de9b7de3098ec775cc222400d2ab8fe214310058b1b8563b769cc006089ddc1f2910526187
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v1.15.0] - 2019-05-16
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Ability to configure Origin, RP ID and RP Name via `WebAuthn.configure`
|
8
|
+
|
3
9
|
## [v1.14.0] - 2019-04-25
|
4
10
|
|
5
11
|
### Added
|
@@ -173,6 +179,7 @@ Note: Both additions should help making it compatible with Chrome for Android 70
|
|
173
179
|
- `WebAuthn::AuthenticatorAttestationResponse.valid?` can be used to validate fido-u2f attestations returned by the browser
|
174
180
|
- Works with ruby 2.5
|
175
181
|
|
182
|
+
[v1.15.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.14.0...v1.15.0/
|
176
183
|
[v1.14.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.13.0...v1.14.0/
|
177
184
|
[v1.13.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.12.0...v1.13.0/
|
178
185
|
[v1.12.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.11.0...v1.12.0/
|
data/README.md
CHANGED
@@ -1,17 +1,23 @@
|
|
1
|
-
# WebAuthn ruby library :key:
|
1
|
+
# WebAuthn ruby server library :key:
|
2
2
|
|
3
|
-
|
3
|
+
Makes your Ruby/Rails web server become a functional [WebAuthn Relying Party](https://www.w3.org/TR/webauthn/#webauthn-relying-party).
|
4
|
+
|
5
|
+
Takes care of the [server-side operations](https://www.w3.org/TR/webauthn/#rp-operations) needed to
|
6
|
+
[register](https://www.w3.org/TR/webauthn/#registration) or [authenticate](https://www.w3.org/TR/webauthn/#authentication)
|
7
|
+
a user [credential](https://www.w3.org/TR/webauthn/#public-key-credential), including the necessary cryptographic checks.
|
4
8
|
|
5
9
|
[![Gem](https://img.shields.io/gem/v/webauthn.svg?style=flat-square)](https://rubygems.org/gems/webauthn)
|
6
10
|
[![Travis](https://img.shields.io/travis/cedarcode/webauthn-ruby/master.svg?style=flat-square)](https://travis-ci.org/cedarcode/webauthn-ruby)
|
7
11
|
[![Join the chat at https://gitter.im/cedarcode/webauthn-ruby](https://badges.gitter.im/cedarcode/webauthn-ruby.svg)](https://gitter.im/cedarcode/webauthn-ruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
8
12
|
|
13
|
+
## Why WebAuthn in my web server?
|
14
|
+
|
15
|
+
- [Security Benefits for WebAuthn Relying Parties](https://www.w3.org/TR/webauthn/#sctn-rp-benefits)
|
16
|
+
|
9
17
|
## What is WebAuthn?
|
10
18
|
|
11
19
|
WebAuthn (Web Authentication) is a W3C standard for secure public-key authentication on the Web supported by all leading browsers and platforms.
|
12
20
|
|
13
|
-
For more:
|
14
|
-
|
15
21
|
- WebAuthn [W3C Recommendation](https://www.w3.org/TR/webauthn/) (i.e. "The Standard")
|
16
22
|
- WebAuthn [intro](https://www.yubico.com/webauthn/) by Yubico
|
17
23
|
- WebAuthn [article](https://en.wikipedia.org/wiki/WebAuthn) in Wikipedia
|
@@ -22,7 +28,7 @@ For more:
|
|
22
28
|
|
23
29
|
This ruby library will help your Ruby/Rails server act as a conforming [_Relying-Party_](https://www.w3.org/TR/webauthn/#relying-party), in WebAuthn terminology. But for the [_Registration_](https://www.w3.org/TR/webauthn/#registration) and [_Authentication_](https://www.w3.org/TR/webauthn/#authentication) ceremonies to fully work, you will also need to add two more pieces to the puzzle, a conforming [User Agent](https://www.w3.org/TR/webauthn/#conforming-user-agents) + [Authenticator](https://www.w3.org/TR/webauthn/#conforming-authenticators) pair.
|
24
30
|
|
25
|
-
|
31
|
+
Known conformant pairs are, for example:
|
26
32
|
|
27
33
|
- Google Chrome for Android 70+ and Android's Fingerprint-based platform authenticator
|
28
34
|
- Microsoft Edge and Windows 10 platform authenticator
|
@@ -54,6 +60,30 @@ Or install it yourself as:
|
|
54
60
|
|
55
61
|
NOTE: 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).
|
56
62
|
|
63
|
+
### Configuration
|
64
|
+
|
65
|
+
For a Rails application this would go in `config/initializers/webauthn.rb`.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
WebAuthn.configure do |config|
|
69
|
+
# This value needs to match `window.location.origin` evaluated by
|
70
|
+
# the User Agent during registration and authentication ceremonies.
|
71
|
+
config.origin = "https://auth.example.com"
|
72
|
+
|
73
|
+
# Relying Party name for display purposes
|
74
|
+
config.rp_name = "Example Inc."
|
75
|
+
|
76
|
+
# You can optionally specify a different Relying Party ID
|
77
|
+
# (https://www.w3.org/TR/webauthn/#relying-party-identifier)
|
78
|
+
# if it differs from the default one.
|
79
|
+
#
|
80
|
+
# In this case the default would be "auth.example.com", but you can set it to
|
81
|
+
# the suffix "example.com"
|
82
|
+
#
|
83
|
+
# config.rp_id = "example.com"
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
57
87
|
### Registration
|
58
88
|
|
59
89
|
#### Initiation phase
|
@@ -91,17 +121,9 @@ attestation_response = WebAuthn::AuthenticatorAttestationResponse.new(
|
|
91
121
|
client_data_json: client_data_json
|
92
122
|
)
|
93
123
|
|
94
|
-
# This value needs to match `window.location.origin` evaluated by
|
95
|
-
# the User Agent as part of the verification phase.
|
96
|
-
expected_origin = "https://www.example.com"
|
97
|
-
|
98
|
-
# In the case that a Relying Party ID (https://www.w3.org/TR/webauthn/#relying-party-identifier) different from `expected_origin` was used on
|
99
|
-
# `navigator.credentials.create`, it needs to specified for verification.
|
100
|
-
# Otherwise, you can ignore passing in this value to the `verify` method below.
|
101
|
-
rp_id = "example.com"
|
102
124
|
|
103
125
|
begin
|
104
|
-
attestation_response.verify(expected_challenge
|
126
|
+
attestation_response.verify(expected_challenge)
|
105
127
|
|
106
128
|
# 1. Register the new user and
|
107
129
|
# 2. Keep Credential ID and Credential Public Key under storage
|
@@ -158,15 +180,6 @@ assertion_response = WebAuthn::AuthenticatorAssertionResponse.new(
|
|
158
180
|
signature: signature
|
159
181
|
)
|
160
182
|
|
161
|
-
# This value needs to match `window.location.origin` evaluated by
|
162
|
-
# the User Agent as part of the verification phase.
|
163
|
-
expected_origin = "https://www.example.com"
|
164
|
-
|
165
|
-
# In the case that a Relying Party ID (https://www.w3.org/TR/webauthn/#relying-party-identifier) different from `expected_origin` was used on
|
166
|
-
# `navigator.credentials.get`, it needs to be specified for verification.
|
167
|
-
# Otherwise, you can ignore passing in this value to the `verify` method below.`
|
168
|
-
rp_id = "example.com"
|
169
|
-
|
170
183
|
# This hash must have the id and its corresponding public key of the
|
171
184
|
# previously stored credential for the user that is attempting to sign in.
|
172
185
|
allowed_credential = {
|
@@ -175,7 +188,7 @@ allowed_credential = {
|
|
175
188
|
}
|
176
189
|
|
177
190
|
begin
|
178
|
-
assertion_response.verify(expected_challenge,
|
191
|
+
assertion_response.verify(expected_challenge, allowed_credentials: [allowed_credential])
|
179
192
|
|
180
193
|
# Sign in the user
|
181
194
|
rescue WebAuthn::VerificationError => e
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "base64"
|
3
4
|
require "jwt"
|
5
|
+
require "webauthn/security_utils"
|
4
6
|
|
5
7
|
module AndroidSafetynet
|
6
8
|
# Decoupled from WebAuthn, candidate for extraction
|
@@ -46,7 +48,7 @@ module AndroidSafetynet
|
|
46
48
|
private
|
47
49
|
|
48
50
|
def valid_nonce?(nonce)
|
49
|
-
payload["nonce"]
|
51
|
+
WebAuthn::SecurityUtils.secure_compare(payload["nonce"], nonce)
|
50
52
|
end
|
51
53
|
|
52
54
|
def valid_attestation_domain?
|
@@ -58,22 +60,11 @@ module AndroidSafetynet
|
|
58
60
|
end
|
59
61
|
|
60
62
|
def valid_signature?
|
61
|
-
JWT.decode(response, leaf_certificate.public_key, true, algorithms:
|
63
|
+
JWT.decode(response, leaf_certificate.public_key, true, algorithms: ["ES256", "RS256"])
|
62
64
|
rescue JWT::VerificationError
|
63
65
|
false
|
64
66
|
end
|
65
67
|
|
66
|
-
def algorithm_for(public_key)
|
67
|
-
case public_key
|
68
|
-
when OpenSSL::PKey::RSA
|
69
|
-
"RS256"
|
70
|
-
when OpenSSL::PKey::EC, OpenSSL::PKey::EC::Point
|
71
|
-
"ES256"
|
72
|
-
else
|
73
|
-
raise "Unsupported algorithm"
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
68
|
def leaf_certificate
|
78
69
|
certificate_chain[0]
|
79
70
|
end
|
data/lib/webauthn.rb
CHANGED
@@ -1,48 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "cose/algorithm"
|
4
3
|
require "webauthn/authenticator_attestation_response"
|
5
4
|
require "webauthn/authenticator_assertion_response"
|
6
|
-
require "webauthn/
|
5
|
+
require "webauthn/configuration"
|
6
|
+
require "webauthn/credential_creation_options"
|
7
|
+
require "webauthn/credential_request_options"
|
7
8
|
require "webauthn/version"
|
8
|
-
|
9
|
-
require "base64"
|
10
|
-
require "securerandom"
|
11
|
-
require "json"
|
12
|
-
|
13
|
-
module WebAuthn
|
14
|
-
DEFAULT_ALGORITHMS = ["ES256", "RS256"].freeze
|
15
|
-
|
16
|
-
DEFAULT_PUB_KEY_CRED_PARAMS = DEFAULT_ALGORITHMS.map do |alg_name|
|
17
|
-
{ type: "public-key", alg: COSE::Algorithm.by_name(alg_name).id }
|
18
|
-
end.freeze
|
19
|
-
|
20
|
-
TYPES = { create: "webauthn.create", get: "webauthn.get" }.freeze
|
21
|
-
|
22
|
-
# TODO: make keyword arguments mandatory in next major version
|
23
|
-
def self.credential_creation_options(
|
24
|
-
rp_name: "web-server",
|
25
|
-
user_name: "web-user",
|
26
|
-
display_name: "web-user",
|
27
|
-
user_id: "1"
|
28
|
-
)
|
29
|
-
{
|
30
|
-
challenge: challenge,
|
31
|
-
pubKeyCredParams: DEFAULT_PUB_KEY_CRED_PARAMS,
|
32
|
-
rp: { name: rp_name },
|
33
|
-
user: { name: user_name, displayName: display_name, id: user_id }
|
34
|
-
}
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.credential_request_options
|
38
|
-
{
|
39
|
-
challenge: challenge,
|
40
|
-
allowCredentials: []
|
41
|
-
}
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.challenge
|
45
|
-
SecureRandom.random_bytes(32)
|
46
|
-
end
|
47
|
-
private_class_method :challenge
|
48
|
-
end
|
@@ -13,13 +13,6 @@ module WebAuthn
|
|
13
13
|
ATTESTATION_FORMAT_ANDROID_KEY = "android-key"
|
14
14
|
ATTESTATION_FORMAT_TPM = "tpm"
|
15
15
|
|
16
|
-
ATTESTATION_TYPE_NONE = "None"
|
17
|
-
ATTESTATION_TYPE_BASIC = "Basic"
|
18
|
-
ATTESTATION_TYPE_SELF = "Self"
|
19
|
-
ATTESTATION_TYPE_ATTCA = "AttCA"
|
20
|
-
ATTESTATION_TYPE_ECDAA = "ECDAA"
|
21
|
-
ATTESTATION_TYPE_BASIC_OR_ATTCA = "Basic_or_AttCA"
|
22
|
-
|
23
16
|
def self.from(format, statement)
|
24
17
|
case format
|
25
18
|
when ATTESTATION_FORMAT_NONE
|
@@ -1,10 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "openssl"
|
4
|
+
require "webauthn/authenticator_data/attested_credential_data"
|
4
5
|
require "webauthn/error"
|
5
6
|
|
6
7
|
module WebAuthn
|
7
8
|
module AttestationStatement
|
9
|
+
ATTESTATION_TYPE_NONE = "None"
|
10
|
+
ATTESTATION_TYPE_BASIC = "Basic"
|
11
|
+
ATTESTATION_TYPE_SELF = "Self"
|
12
|
+
ATTESTATION_TYPE_ATTCA = "AttCA"
|
13
|
+
ATTESTATION_TYPE_ECDAA = "ECDAA"
|
14
|
+
ATTESTATION_TYPE_BASIC_OR_ATTCA = "Basic_or_AttCA"
|
15
|
+
|
8
16
|
class Base
|
9
17
|
class NotSupportedError < Error; end
|
10
18
|
|
@@ -1,8 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "cose/algorithm"
|
3
4
|
require "cose/key"
|
4
5
|
require "tpm/constants"
|
5
6
|
require "tpm/t_public"
|
7
|
+
require "webauthn/attestation_statement/base"
|
6
8
|
|
7
9
|
module WebAuthn
|
8
10
|
module AttestationStatement
|
@@ -19,7 +21,7 @@ module WebAuthn
|
|
19
21
|
}.freeze
|
20
22
|
|
21
23
|
COSE_TO_TPM_CURVE = {
|
22
|
-
COSE::Key::
|
24
|
+
COSE::Key::Curve.by_name("P-256").id => ::TPM::ECC_NIST_P256
|
23
25
|
}.freeze
|
24
26
|
|
25
27
|
def initialize(data)
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require "cose/algorithm"
|
4
4
|
require "cose/key"
|
5
5
|
require "webauthn/attestation_statement/fido_u2f/public_key"
|
6
|
+
require "webauthn/authenticator_data"
|
6
7
|
require "webauthn/authenticator_response"
|
7
8
|
require "webauthn/signature_verifier"
|
8
9
|
|
@@ -19,7 +20,7 @@ module WebAuthn
|
|
19
20
|
@signature = signature
|
20
21
|
end
|
21
22
|
|
22
|
-
def verify(expected_challenge, expected_origin, allowed_credentials:, rp_id: nil)
|
23
|
+
def verify(expected_challenge, expected_origin = nil, allowed_credentials:, rp_id: nil)
|
23
24
|
super(expected_challenge, expected_origin, rp_id: rp_id)
|
24
25
|
|
25
26
|
verify_item(:credential, allowed_credentials)
|
@@ -1,8 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "base64"
|
4
|
+
require "webauthn/client_data"
|
3
5
|
require "webauthn/error"
|
6
|
+
require "webauthn/security_utils"
|
4
7
|
|
5
8
|
module WebAuthn
|
9
|
+
TYPES = { create: "webauthn.create", get: "webauthn.get" }.freeze
|
10
|
+
|
6
11
|
class VerificationError < Error; end
|
7
12
|
|
8
13
|
class AuthenticatorDataVerificationError < VerificationError; end
|
@@ -18,7 +23,10 @@ module WebAuthn
|
|
18
23
|
@client_data_json = client_data_json
|
19
24
|
end
|
20
25
|
|
21
|
-
def verify(expected_challenge, expected_origin, rp_id: nil)
|
26
|
+
def verify(expected_challenge, expected_origin = nil, rp_id: nil)
|
27
|
+
expected_origin ||= WebAuthn.configuration.origin || raise("Unspecified expected origin")
|
28
|
+
rp_id ||= WebAuthn.configuration.rp_id
|
29
|
+
|
22
30
|
verify_item(:type)
|
23
31
|
verify_item(:token_binding)
|
24
32
|
verify_item(:challenge, expected_challenge)
|
@@ -67,7 +75,7 @@ module WebAuthn
|
|
67
75
|
end
|
68
76
|
|
69
77
|
def valid_origin?(expected_origin)
|
70
|
-
client_data.origin == expected_origin
|
78
|
+
expected_origin && (client_data.origin == expected_origin)
|
71
79
|
end
|
72
80
|
|
73
81
|
def valid_rp_id?(rp_id)
|
data/lib/webauthn/client_data.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module WebAuthn
|
4
|
+
def self.configuration
|
5
|
+
@configuration ||= Configuration.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.configure
|
9
|
+
yield(configuration)
|
10
|
+
end
|
11
|
+
|
12
|
+
class Configuration
|
13
|
+
attr_accessor :origin
|
14
|
+
attr_accessor :rp_id
|
15
|
+
attr_accessor :rp_name
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "cose/algorithm"
|
4
|
+
require "webauthn/credential_options"
|
5
|
+
require "webauthn/credential_rp_entity"
|
6
|
+
require "webauthn/credential_user_entity"
|
7
|
+
|
8
|
+
module WebAuthn
|
9
|
+
# TODO: make keyword arguments mandatory in next major version
|
10
|
+
def self.credential_creation_options(rp_name: nil, user_name: "web-user", display_name: "web-user", user_id: "1")
|
11
|
+
CredentialCreationOptions.new(
|
12
|
+
rp_name: rp_name, user_id: user_id, user_name: user_name, user_display_name: display_name
|
13
|
+
).to_h
|
14
|
+
end
|
15
|
+
|
16
|
+
class CredentialCreationOptions < CredentialOptions
|
17
|
+
DEFAULT_ALGORITHMS = ["ES256", "RS256"].freeze
|
18
|
+
DEFAULT_RP_NAME = "web-server"
|
19
|
+
|
20
|
+
DEFAULT_PUB_KEY_CRED_PARAMS = DEFAULT_ALGORITHMS.map do |alg_name|
|
21
|
+
{ type: "public-key", alg: COSE::Algorithm.by_name(alg_name).id }
|
22
|
+
end.freeze
|
23
|
+
|
24
|
+
def initialize(user_id:, user_name:, user_display_name: nil, rp_name: nil)
|
25
|
+
@user_id = user_id
|
26
|
+
@user_name = user_name
|
27
|
+
@user_display_name = user_display_name
|
28
|
+
@rp_name = rp_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_h
|
32
|
+
{
|
33
|
+
challenge: challenge,
|
34
|
+
pubKeyCredParams: pub_key_cred_params,
|
35
|
+
user: { id: user.id, name: user.name, displayName: user.display_name },
|
36
|
+
rp: { name: rp.name }
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def pub_key_cred_params
|
41
|
+
DEFAULT_PUB_KEY_CRED_PARAMS
|
42
|
+
end
|
43
|
+
|
44
|
+
def rp
|
45
|
+
@rp ||= CredentialRPEntity.new(name: rp_name || configuration.rp_name || DEFAULT_RP_NAME)
|
46
|
+
end
|
47
|
+
|
48
|
+
def user
|
49
|
+
@user ||= CredentialUserEntity.new(id: user_id, name: user_name, display_name: user_display_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
attr_reader :user_id, :user_name, :user_display_name, :rp_name
|
55
|
+
|
56
|
+
def configuration
|
57
|
+
WebAuthn.configuration
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "webauthn/credential_options"
|
4
|
+
|
5
|
+
module WebAuthn
|
6
|
+
def self.credential_request_options
|
7
|
+
CredentialRequestOptions.new.to_h
|
8
|
+
end
|
9
|
+
|
10
|
+
class CredentialRequestOptions < CredentialOptions
|
11
|
+
def to_h
|
12
|
+
{ challenge: challenge, allowCredentials: allow_credentials }
|
13
|
+
end
|
14
|
+
|
15
|
+
def allow_credentials
|
16
|
+
[]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "webauthn/credential_entity"
|
4
|
+
|
5
|
+
module WebAuthn
|
6
|
+
class CredentialUserEntity < CredentialEntity
|
7
|
+
attr_reader :id, :display_name
|
8
|
+
|
9
|
+
def initialize(id:, display_name: nil, **keyword_arguments)
|
10
|
+
super(**keyword_arguments)
|
11
|
+
|
12
|
+
@id = id
|
13
|
+
@display_name = display_name || name
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -8,8 +8,6 @@ require "webauthn/fake_authenticator/authenticator_data"
|
|
8
8
|
|
9
9
|
module WebAuthn
|
10
10
|
class FakeAuthenticator
|
11
|
-
AAGUID = SecureRandom.random_bytes(16)
|
12
|
-
|
13
11
|
def initialize
|
14
12
|
@credentials = {}
|
15
13
|
end
|
@@ -32,7 +30,13 @@ module WebAuthn
|
|
32
30
|
attestation_object
|
33
31
|
end
|
34
32
|
|
35
|
-
def get_assertion(
|
33
|
+
def get_assertion(
|
34
|
+
rp_id:,
|
35
|
+
client_data_hash:,
|
36
|
+
user_present: true,
|
37
|
+
user_verified: false,
|
38
|
+
aaguid: AuthenticatorData::AAGUID
|
39
|
+
)
|
36
40
|
credential_options = credentials[rp_id]
|
37
41
|
|
38
42
|
if credential_options
|
@@ -7,8 +7,10 @@ require "securerandom"
|
|
7
7
|
module WebAuthn
|
8
8
|
class FakeAuthenticator
|
9
9
|
class AuthenticatorData
|
10
|
+
AAGUID = SecureRandom.random_bytes(16)
|
11
|
+
|
10
12
|
def initialize(rp_id_hash:, credential: nil, sign_count: 0, user_present: true, user_verified: !user_present,
|
11
|
-
aaguid:
|
13
|
+
aaguid: AAGUID)
|
12
14
|
@rp_id_hash = rp_id_hash
|
13
15
|
@credential = credential
|
14
16
|
@sign_count = sign_count
|
@@ -100,9 +102,9 @@ module WebAuthn
|
|
100
102
|
key.instance_variable_set(:@alg, -257)
|
101
103
|
when OpenSSL::PKey::EC::Point
|
102
104
|
alg = {
|
103
|
-
COSE::Key::
|
104
|
-
COSE::Key::
|
105
|
-
COSE::Key::
|
105
|
+
COSE::Key::Curve.by_name("P-256").id => -7,
|
106
|
+
COSE::Key::Curve.by_name("P-384").id => -35,
|
107
|
+
COSE::Key::Curve.by_name("P-521").id => -36
|
106
108
|
}
|
107
109
|
|
108
110
|
key = COSE::Key::EC2.from_pkey(credential[:public_key])
|
data/lib/webauthn/fake_client.rb
CHANGED
data/lib/webauthn/version.rb
CHANGED
data/webauthn.gemspec
CHANGED
@@ -10,8 +10,9 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.authors = ["Gonzalo Rodriguez", "Braulio Martinez"]
|
11
11
|
spec.email = ["gonzalo@cedarcode.com", "braulio@cedarcode.com"]
|
12
12
|
|
13
|
-
spec.summary = "WebAuthn ruby library"
|
14
|
-
spec.description =
|
13
|
+
spec.summary = "WebAuthn ruby server library"
|
14
|
+
spec.description = 'WebAuthn ruby server library ― Make your application a W3C Web Authentication conformant
|
15
|
+
Relying Party and allow your users to authenticate with U2F and FIDO 2.0 authenticators.'
|
15
16
|
spec.homepage = "https://github.com/cedarcode/webauthn-ruby"
|
16
17
|
spec.license = "MIT"
|
17
18
|
|
@@ -32,7 +33,7 @@ Gem::Specification.new do |spec|
|
|
32
33
|
|
33
34
|
spec.add_dependency "bindata", "~> 2.4"
|
34
35
|
spec.add_dependency "cbor", "~> 0.5.9"
|
35
|
-
spec.add_dependency "cose", "~> 0.
|
36
|
+
spec.add_dependency "cose", "~> 0.7.0"
|
36
37
|
spec.add_dependency "jwt", [">= 1.5", "< 3.0"]
|
37
38
|
spec.add_dependency "openssl", "~> 2.0"
|
38
39
|
spec.add_dependency "securecompare", "~> 1.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: 1.
|
4
|
+
version: 1.15.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: 2019-
|
12
|
+
date: 2019-05-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bindata
|
@@ -45,14 +45,14 @@ dependencies:
|
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: 0.
|
48
|
+
version: 0.7.0
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: 0.
|
55
|
+
version: 0.7.0
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: jwt
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -191,8 +191,9 @@ dependencies:
|
|
191
191
|
- - '='
|
192
192
|
- !ruby/object:Gem::Version
|
193
193
|
version: 0.67.2
|
194
|
-
description:
|
195
|
-
|
194
|
+
description: |-
|
195
|
+
WebAuthn ruby server library ― Make your application a W3C Web Authentication conformant
|
196
|
+
Relying Party and allow your users to authenticate with U2F and FIDO 2.0 authenticators.
|
196
197
|
email:
|
197
198
|
- gonzalo@cedarcode.com
|
198
199
|
- braulio@cedarcode.com
|
@@ -243,6 +244,13 @@ files:
|
|
243
244
|
- lib/webauthn/authenticator_data/attested_credential_data.rb
|
244
245
|
- lib/webauthn/authenticator_response.rb
|
245
246
|
- lib/webauthn/client_data.rb
|
247
|
+
- lib/webauthn/configuration.rb
|
248
|
+
- lib/webauthn/credential_creation_options.rb
|
249
|
+
- lib/webauthn/credential_entity.rb
|
250
|
+
- lib/webauthn/credential_options.rb
|
251
|
+
- lib/webauthn/credential_request_options.rb
|
252
|
+
- lib/webauthn/credential_rp_entity.rb
|
253
|
+
- lib/webauthn/credential_user_entity.rb
|
246
254
|
- lib/webauthn/error.rb
|
247
255
|
- lib/webauthn/fake_authenticator.rb
|
248
256
|
- lib/webauthn/fake_authenticator/attestation_object.rb
|
@@ -277,5 +285,5 @@ requirements: []
|
|
277
285
|
rubygems_version: 3.0.3
|
278
286
|
signing_key:
|
279
287
|
specification_version: 4
|
280
|
-
summary: WebAuthn ruby library
|
288
|
+
summary: WebAuthn ruby server library
|
281
289
|
test_files: []
|