webauthn 1.0.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 004107dfab888cb866245f75d634764ffb859974f12e5d70b30304a6d8c25ce1
4
- data.tar.gz: 2cdfacf2e938a030f494717d644ae394f1f55a759e5eff125face25f7eda16d7
3
+ metadata.gz: d6d2e58280b0751e346931762bbd6985f7ac0c89dc7a2ac98ae4658e98b6f68c
4
+ data.tar.gz: ca2ee35c669f2a31dd7770212deef3712b3089f34e119124977eac70f91cc3d7
5
5
  SHA512:
6
- metadata.gz: c3080d2ca2560908ff75ab0a100226c9526e3909cdbadc6d166050fbea710b0f48f52f56ea315ff7e2e98d4a877ad5da1e85a12cb9f3f57784b99f5a8416e76a
7
- data.tar.gz: e1d08103e408ec0e9b4561d1b24b886a013392ddf13044cf62b13046ea8754aec2ff184f75d48ec1710d4c53bb841f87289e8bbe5c2d5c496f40b683a1b353be
6
+ metadata.gz: df657808c9a692d6f32b1256917dfb9867abd9fa6dc117059cb92f1d8cb80beb652af7d71b9881add353b20a8dad85cd00448ed8d6a9205070ed6d627882ea58
7
+ data.tar.gz: 9d417117edd82f9072dad0a98fafe4707121e2fb3cfb62678195e324d9bb68e1f00c35dbe8fc1721abd34ec1d09259decf2c620b4e56af2638cf3ec6ec98e850
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.1.0] - 2018-10-04
4
+
5
+ ## Added
6
+
7
+ - _Registration_ ceremony
8
+ - `WebAuthn::AuthenticatorAttestationResponse.valid?` optionaly accepts rp_id. Thank you @sorah!
9
+ - _Authentication_ ceremony
10
+ - `WebAuthn::AuthenticatorAssertionResponse.valid?` optionaly accepts rp_id.
11
+
3
12
  ## [v1.0.0] - 2018-09-07
4
13
 
5
14
  ### Added
@@ -51,6 +60,7 @@
51
60
  - `WebAuthn::AuthenticatorAttestationResponse.valid?` can be used to validate fido-u2f attestations returned by the browser
52
61
  - Works with ruby 2.5
53
62
 
63
+ [v1.1.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.0.0...v1.1.0/
54
64
  [v1.0.0]: https://github.com/cedarcode/webauthn-ruby/compare/v0.2.0...v1.0.0/
55
65
  [v0.2.0]: https://github.com/cedarcode/webauthn-ruby/compare/v0.1.0...v0.2.0/
56
66
  [v0.1.0]: https://github.com/cedarcode/webauthn-ruby/compare/v0.0.0...v0.1.0/
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Easily implement WebAuthn in your ruby/rails app
4
4
 
5
5
  [![Gem](https://img.shields.io/gem/v/webauthn.svg?style=flat-square)](https://rubygems.org/gems/webauthn)
6
- [![Travis](https://img.shields.io/travis/cedarcode/webauthn-ruby.svg?style=flat-square)](https://travis-ci.org/cedarcode/webauthn-ruby)
6
+ [![Travis](https://img.shields.io/travis/cedarcode/webauthn-ruby/master.svg?style=flat-square)](https://travis-ci.org/cedarcode/webauthn-ruby)
7
7
 
8
8
  ## What is WebAuthn?
9
9
 
@@ -135,7 +135,7 @@ original_origin = "https://www.example.com"
135
135
  # previously stored credential for the user that is attempting to sign in.
136
136
  allowed_credential = {
137
137
  id: credential_id,
138
- publick_key: credential_public_key
138
+ public_key: credential_public_key
139
139
  }
140
140
 
141
141
  if assertion_response.valid?(original_challenge, original_origin, allowed_credential: allowed_credential)
@@ -12,12 +12,16 @@ module WebAuthn
12
12
  @signature = signature
13
13
  end
14
14
 
15
- def valid?(original_challenge, original_origin, allowed_credentials:)
16
- super(original_challenge, original_origin) &&
15
+ def valid?(original_challenge, original_origin, allowed_credentials:, rp_id: nil)
16
+ super(original_challenge, original_origin, rp_id: rp_id) &&
17
17
  valid_credential?(allowed_credentials) &&
18
18
  valid_signature?(credential_public_key(allowed_credentials))
19
19
  end
20
20
 
21
+ def authenticator_data
22
+ @authenticator_data ||= WebAuthn::AuthenticatorData.new(authenticator_data_bytes)
23
+ end
24
+
21
25
  private
22
26
 
23
27
  attr_reader :credential_id, :authenticator_data_bytes, :signature
@@ -42,10 +46,6 @@ module WebAuthn
42
46
  allowed_credential_ids.include?(credential_id)
43
47
  end
44
48
 
45
- def authenticator_data
46
- @authenticator_data ||= WebAuthn::AuthenticatorData.new(authenticator_data_bytes)
47
- end
48
-
49
49
  def credential_public_key(allowed_credentials)
50
50
  matched_credential = allowed_credentials.find do |credential|
51
51
  credential[:id] == credential_id
@@ -17,7 +17,7 @@ module WebAuthn
17
17
  @attestation_object = attestation_object
18
18
  end
19
19
 
20
- def valid?(original_challenge, original_origin)
20
+ def valid?(original_challenge, original_origin, rp_id: nil)
21
21
  super &&
22
22
  attestation_statement.valid?(authenticator_data, client_data.hash)
23
23
  end
@@ -26,10 +26,6 @@ module WebAuthn
26
26
  authenticator_data.credential
27
27
  end
28
28
 
29
- private
30
-
31
- attr_reader :attestation_object
32
-
33
29
  def attestation_statement
34
30
  @attestation_statement ||=
35
31
  WebAuthn::AttestationStatement.from(attestation["fmt"], attestation["attStmt"])
@@ -47,6 +43,10 @@ module WebAuthn
47
43
  @attestation ||= CBOR.decode(attestation_object)
48
44
  end
49
45
 
46
+ private
47
+
48
+ attr_reader :attestation_object
49
+
50
50
  def type
51
51
  WebAuthn::TYPES[:create]
52
52
  end
@@ -10,6 +10,8 @@ module WebAuthn
10
10
  FLAGS_LENGTH = 1
11
11
  SIGN_COUNT_LENGTH = 4
12
12
 
13
+ SIGN_COUNT_POSITION = RP_ID_HASH_LENGTH + FLAGS_LENGTH
14
+
13
15
  USER_PRESENT_FLAG_POSITION = 0
14
16
  ATTESTED_CREDENTIAL_DATA_INCLUDED_FLAG_POSITION = 6
15
17
 
@@ -17,6 +19,8 @@ module WebAuthn
17
19
  @data = data
18
20
  end
19
21
 
22
+ attr_reader :data
23
+
20
24
  def valid?
21
25
  if attested_credential_data_included?
22
26
  data.length > base_length && attested_credential_data.valid?
@@ -29,6 +33,10 @@ module WebAuthn
29
33
  flags[USER_PRESENT_FLAG_POSITION] == "1"
30
34
  end
31
35
 
36
+ def attested_credential_data_included?
37
+ flags[ATTESTED_CREDENTIAL_DATA_INCLUDED_FLAG_POSITION] == "1"
38
+ end
39
+
32
40
  def rp_id_hash
33
41
  @rp_id_hash ||=
34
42
  if valid?
@@ -40,15 +48,21 @@ module WebAuthn
40
48
  attested_credential_data.credential
41
49
  end
42
50
 
43
- private
44
-
45
- attr_reader :data
51
+ def sign_count
52
+ @sign_count ||= data_at(SIGN_COUNT_POSITION, SIGN_COUNT_LENGTH).unpack1('L>')
53
+ end
46
54
 
47
55
  def attested_credential_data
48
56
  @attested_credential_data ||=
49
57
  AttestedCredentialData.new(data_at(attested_credential_data_position))
50
58
  end
51
59
 
60
+ def flags
61
+ @flags ||= data_at(flags_position, FLAGS_LENGTH).unpack1("b*")
62
+ end
63
+
64
+ private
65
+
52
66
  def attested_credential_data_position
53
67
  base_length
54
68
  end
@@ -57,18 +71,10 @@ module WebAuthn
57
71
  RP_ID_HASH_LENGTH + FLAGS_LENGTH + SIGN_COUNT_LENGTH
58
72
  end
59
73
 
60
- def flags
61
- @flags ||= data_at(flags_position, FLAGS_LENGTH).unpack1("b*")
62
- end
63
-
64
74
  def flags_position
65
75
  RP_ID_HASH_LENGTH
66
76
  end
67
77
 
68
- def attested_credential_data_included?
69
- flags[ATTESTED_CREDENTIAL_DATA_INCLUDED_FLAG_POSITION] == "1"
70
- end
71
-
72
78
  def data_at(position, length = nil)
73
79
  length ||= data.size - position
74
80
 
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "ostruct"
4
3
  require "webauthn/authenticator_data/attested_credential_data/public_key_u2f"
5
4
 
6
5
  module WebAuthn
@@ -12,7 +11,8 @@ module WebAuthn
12
11
 
13
12
  UINT16_BIG_ENDIAN_FORMAT = "n*"
14
13
 
15
- class Credential < OpenStruct; end
14
+ # FIXME: use keyword_init when we dropped Ruby 2.4 support
15
+ Credential = Struct.new(:id, :public_key)
16
16
 
17
17
  def initialize(data)
18
18
  @data = data
@@ -25,7 +25,7 @@ module WebAuthn
25
25
  def credential
26
26
  @credential ||=
27
27
  if id
28
- Credential.new(id: id, public_key: public_key.to_str)
28
+ Credential.new(id, public_key.to_str)
29
29
  end
30
30
  end
31
31
 
@@ -6,15 +6,19 @@ module WebAuthn
6
6
  @client_data_json = client_data_json
7
7
  end
8
8
 
9
- def valid?(original_challenge, original_origin)
9
+ def valid?(original_challenge, original_origin, rp_id: nil)
10
10
  valid_type? &&
11
11
  valid_challenge?(original_challenge) &&
12
12
  valid_origin?(original_origin) &&
13
- valid_rp_id?(original_origin) &&
13
+ valid_rp_id?(rp_id || rp_id_from_origin(original_origin)) &&
14
14
  authenticator_data.valid? &&
15
15
  authenticator_data.user_present?
16
16
  end
17
17
 
18
+ def client_data
19
+ @client_data ||= WebAuthn::ClientData.new(client_data_json)
20
+ end
21
+
18
22
  private
19
23
 
20
24
  attr_reader :client_data_json
@@ -23,10 +27,6 @@ module WebAuthn
23
27
  client_data.type == type
24
28
  end
25
29
 
26
- def client_data
27
- @client_data ||= WebAuthn::ClientData.new(client_data_json)
28
- end
29
-
30
30
  def valid_challenge?(original_challenge)
31
31
  WebAuthn::Utils.authenticator_decode(client_data.challenge) == original_challenge
32
32
  end
@@ -35,10 +35,12 @@ module WebAuthn
35
35
  client_data.origin == original_origin
36
36
  end
37
37
 
38
- def valid_rp_id?(original_origin)
39
- domain = URI.parse(original_origin).host
38
+ def valid_rp_id?(rp_id)
39
+ OpenSSL::Digest::SHA256.digest(rp_id) == authenticator_data.rp_id_hash
40
+ end
40
41
 
41
- OpenSSL::Digest::SHA256.digest(domain) == authenticator_data.rp_id_hash
42
+ def rp_id_from_origin(original_origin)
43
+ URI.parse(original_origin).host
42
44
  end
43
45
 
44
46
  def type
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebAuthn
4
- VERSION = "1.0.0"
4
+ VERSION = "1.1.0"
5
5
  end
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.0.0
4
+ version: 1.1.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: 2018-09-07 00:00:00.000000000 Z
12
+ date: 2018-10-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cbor
@@ -167,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
167
  version: '0'
168
168
  requirements: []
169
169
  rubyforge_project:
170
- rubygems_version: 2.7.7
170
+ rubygems_version: 2.7.6
171
171
  signing_key:
172
172
  specification_version: 4
173
173
  summary: WebAuthn in ruby ― Ruby implementation of a WebAuthn Relying Party