webauthn 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b133f46bd003c9bfb9a8557bb8caeca7239fcd6c185f78e74e0ae578444d576e
4
- data.tar.gz: 14a32debc72ddcfe7e752118ebd4db832b8a46a5628ee54830f30eada4159bcf
3
+ metadata.gz: 3b23698bdd722a0cda45be7ee9d5ba528f966eb98304a50069242f0a25dcd259
4
+ data.tar.gz: 4d7bf8874268cbbbfa75136006af9dc5a824b25d3f0522c5f2046092261bae5d
5
5
  SHA512:
6
- metadata.gz: 9b4ff5cee18575b517473fef7d8000d7e41f113b178378e64a4d2b9036d248f4295edd846a519ab76036a270c3066020fbe44847019812c2a5758f2b1b428f4c
7
- data.tar.gz: f3ab22709cbf537982e163acc60dbe114217f223b18cb4cf681a3d932e2f31276f8286091e49da392356c1958ada7e2c07a5b86b48d57b597f965a57c1bcf63d
6
+ metadata.gz: bf2d6697ee0c34cccbb1f5f9765e70efe1a8062f73b35cb900894c59f512d81157a836046e8006c9c6d5b0a0b3040f9c76a83417928d0ff9fbaba2db1893aaef
7
+ data.tar.gz: 2952c2573b030ffbba7837f2ba299e73c7a4e09a3a46b4a7a19c7875b4ea5394a8af00059dda69ae4c3dc34b1531b3aad3d1d1445dc4000260b3cfc4e5e23a98
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
@@ -7,7 +7,11 @@
7
7
 
8
8
  name: build
9
9
 
10
- on: push
10
+ on:
11
+ push:
12
+ branches: [master]
13
+ pull_request:
14
+ types: [opened, synchronize]
11
15
 
12
16
  jobs:
13
17
  test:
@@ -24,7 +28,7 @@ jobs:
24
28
  - '2.5'
25
29
  - truffleruby
26
30
  steps:
27
- - uses: actions/checkout@v3
31
+ - uses: actions/checkout@v4
28
32
  - uses: ruby/setup-ruby@v1
29
33
  with:
30
34
  ruby-version: ${{ matrix.ruby }}
@@ -14,7 +14,7 @@ jobs:
14
14
  runs-on: ubuntu-latest
15
15
 
16
16
  steps:
17
- - uses: actions/checkout@v3
17
+ - uses: actions/checkout@v4
18
18
  - name: Block autosquash commits
19
19
  uses: xt0rted/block-autosquash-commits-action@v2
20
20
  with:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [v3.1.0] - 2023-12-26
4
+
5
+ ### Added
6
+
7
+ - Add support for optional `authenticator_attachment` in `PublicKeyCredential`. #370 [@8ma10s]
8
+
9
+ ### Fixed
10
+
11
+ - Fix circular require warning between `webauthn/relying_party` and `webauthn/credential`. #389 [@bdewater]
12
+ - Correctly verify attestation that contains just a batch certificate that is present in the attestation root certificates. #406 [@santiagorodriguez96]
13
+
14
+ ### Changed
15
+
16
+ - Inlined `base64` implementation. #402 [@olleolleolle]
17
+ - Raise a more descriptive error if input `challenge` is `nil` when verifying the `PublicKeyCredential`. #413 [@soartec-lab]
18
+
3
19
  ## [v3.0.0] - 2023-02-15
4
20
 
5
21
  ### Added
@@ -358,6 +374,7 @@ Note: Both additions should help making it compatible with Chrome for Android 70
358
374
  - `WebAuthn::AuthenticatorAttestationResponse.valid?` can be used to validate fido-u2f attestations returned by the browser
359
375
  - Works with ruby 2.5
360
376
 
377
+ [v3.1.0]: https://github.com/cedarcode/webauthn-ruby/compare/v3.0.0...v3.1.0/
361
378
  [v3.0.0]: https://github.com/cedarcode/webauthn-ruby/compare/2-stable...v3.0.0/
362
379
  [v3.0.0.alpha2]: https://github.com/cedarcode/webauthn-ruby/compare/2-stable...v3.0.0.alpha2/
363
380
  [v3.0.0.alpha1]: https://github.com/cedarcode/webauthn-ruby/compare/v2.3.0...v3.0.0.alpha1
data/README.md CHANGED
@@ -6,7 +6,7 @@ For the current release version see https://github.com/cedarcode/webauthn-ruby/b
6
6
  ![banner](assets/webauthn-ruby.png)
7
7
 
8
8
  [![Gem](https://img.shields.io/gem/v/webauthn.svg?style=flat-square)](https://rubygems.org/gems/webauthn)
9
- [![Travis](https://img.shields.io/travis/cedarcode/webauthn-ruby/master.svg?style=flat-square)](https://travis-ci.com/cedarcode/webauthn-ruby)
9
+ [![Build](https://github.com/cedarcode/webauthn-ruby/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/cedarcode/webauthn-ruby/actions/workflows/build.yml)
10
10
  [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-informational.svg?style=flat-square)](https://conventionalcommits.org)
11
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)
12
12
 
@@ -59,7 +59,7 @@ Intead of the [Global Configuration](../README.md#configuration) you place in `c
59
59
 
60
60
  **DISCLAIMER: This API was released on version 3.0.0.alpha1 and is still under evaluation. Although it has been throughly tested and it is fully functional it might be changed until the final release of version 3.0.0.**
61
61
 
62
- The explanation for each ceremony can be found in depth in [Credential Registration](../README.md#credential-registration) and [Credential Authentication](../README.md#credential-authentication) but if you choose this instance based approach to define your WebAuthn configurations and assuming `relying_party` is the result of an instance you get through `WebAuthn::RelytingParty.new(...)` the code in those explanations needs to be updated to:
62
+ The explanation for each ceremony can be found in depth in [Credential Registration](../README.md#credential-registration) and [Credential Authentication](../README.md#credential-authentication) but if you choose this instance based approach to define your WebAuthn configurations and assuming `relying_party` is the result of an instance you get through `WebAuthn::RelyingParty.new(...)` the code in those explanations needs to be updated to:
63
63
 
64
64
  ### Credential Registration
65
65
 
@@ -73,7 +73,7 @@ end
73
73
 
74
74
  options = relying_party.options_for_registration(
75
75
  user: { id: user.webauthn_id, name: user.name },
76
- exclude: user.credentials.map { |c| c.webauthn_id }
76
+ exclude: user.credentials.map { |c| c.external_id }
77
77
  )
78
78
 
79
79
  # Store the newly generated challenge somewhere so you can have it
@@ -106,7 +106,7 @@ begin
106
106
 
107
107
  # Store Credential ID, Credential Public Key and Sign Count for future authentications
108
108
  user.credentials.create!(
109
- webauthn_id: webauthn_credential.id,
109
+ external_id: webauthn_credential.id,
110
110
  public_key: webauthn_credential.public_key,
111
111
  sign_count: webauthn_credential.sign_count
112
112
  )
@@ -120,7 +120,7 @@ end
120
120
  #### Initiation phase
121
121
 
122
122
  ```ruby
123
- options = relying_party.options_for_get(allow: user.credentials.map { |c| c.webauthn_id })
123
+ options = relying_party.options_for_authentication(allow: user.credentials.map { |c| c.webauthn_id })
124
124
 
125
125
  # Store the newly generated challenge somewhere so you can have it
126
126
  # for the verification phase.
@@ -148,9 +148,9 @@ begin
148
148
  webauthn_credential, stored_credential = relying_party.verify_authentication(
149
149
  params[:publicKeyCredential],
150
150
  session[:authentication_challenge]
151
- ) do
151
+ ) do |webauthn_credential|
152
152
  # the returned object needs to respond to #public_key and #sign_count
153
- user.credentials.find_by(webauthn_id: webauthn_credential.id)
153
+ user.credentials.find_by(external_id: webauthn_credential.id)
154
154
  end
155
155
 
156
156
  # Update the stored credential sign count with the value from `webauthn_credential.sign_count`
@@ -102,6 +102,15 @@ module WebAuthn
102
102
  end
103
103
 
104
104
  def valid_certificate_chain?(aaguid: nil, attestation_certificate_key_id: nil)
105
+ root_certificates = root_certificates(
106
+ aaguid: aaguid,
107
+ attestation_certificate_key_id: attestation_certificate_key_id
108
+ )
109
+
110
+ if certificates&.one? && root_certificates.include?(attestation_certificate)
111
+ return true
112
+ end
113
+
105
114
  attestation_root_certificates_store(
106
115
  aaguid: aaguid,
107
116
  attestation_certificate_key_id: attestation_certificate_key_id
@@ -4,7 +4,6 @@ require "webauthn/public_key_credential/creation_options"
4
4
  require "webauthn/public_key_credential/request_options"
5
5
  require "webauthn/public_key_credential_with_assertion"
6
6
  require "webauthn/public_key_credential_with_attestation"
7
- require "webauthn/relying_party"
8
7
 
9
8
  module WebAuthn
10
9
  module Credential
@@ -20,9 +20,12 @@ module WebAuthn
20
20
  def encode(data)
21
21
  case encoding
22
22
  when :base64
23
- Base64.strict_encode64(data)
23
+ [data].pack("m0") # Base64.strict_encode64(data)
24
24
  when :base64url
25
- Base64.urlsafe_encode64(data, padding: false)
25
+ data = [data].pack("m0") # Base64.urlsafe_encode64(data, padding: false)
26
+ data.chomp!("==") or data.chomp!("=")
27
+ data.tr!("+/", "-_")
28
+ data
26
29
  when nil, false
27
30
  data
28
31
  else
@@ -33,9 +36,15 @@ module WebAuthn
33
36
  def decode(data)
34
37
  case encoding
35
38
  when :base64
36
- Base64.strict_decode64(data)
39
+ data.unpack1("m0") # Base64.strict_decode64(data)
37
40
  when :base64url
38
- Base64.urlsafe_decode64(data)
41
+ if !data.end_with?("=") && data.length % 4 != 0 # Base64.urlsafe_decode64(data)
42
+ data = data.ljust((data.length + 3) & ~3, "=")
43
+ data.tr!("-_", "+/")
44
+ else
45
+ data = data.tr("-_", "+/")
46
+ end
47
+ data.unpack1("m0")
39
48
  when nil, false
40
49
  data
41
50
  else
@@ -64,6 +64,7 @@ module WebAuthn
64
64
  "type" => "public-key",
65
65
  "id" => internal_encoder.encode(id),
66
66
  "rawId" => encoder.encode(id),
67
+ "authenticatorAttachment" => 'platform',
67
68
  "clientExtensionResults" => extensions,
68
69
  "response" => {
69
70
  "attestationObject" => encoder.encode(attestation_object),
@@ -108,6 +109,7 @@ module WebAuthn
108
109
  "id" => internal_encoder.encode(assertion[:credential_id]),
109
110
  "rawId" => encoder.encode(assertion[:credential_id]),
110
111
  "clientExtensionResults" => extensions,
112
+ "authenticatorAttachment" => 'platform',
111
113
  "response" => {
112
114
  "clientDataJSON" => encoder.encode(client_data_json),
113
115
  "authenticatorData" => encoder.encode(assertion[:authenticator_data]),
@@ -4,7 +4,9 @@ require "webauthn/encoder"
4
4
 
5
5
  module WebAuthn
6
6
  class PublicKeyCredential
7
- attr_reader :type, :id, :raw_id, :client_extension_outputs, :response
7
+ class InvalidChallengeError < Error; end
8
+
9
+ attr_reader :type, :id, :raw_id, :client_extension_outputs, :authenticator_attachment, :response
8
10
 
9
11
  def self.from_client(credential, relying_party: WebAuthn.configuration.relying_party)
10
12
  new(
@@ -12,6 +14,7 @@ module WebAuthn
12
14
  id: credential["id"],
13
15
  raw_id: relying_party.encoder.decode(credential["rawId"]),
14
16
  client_extension_outputs: credential["clientExtensionResults"],
17
+ authenticator_attachment: credential["authenticatorAttachment"],
15
18
  response: response_class.from_client(credential["response"], relying_party: relying_party),
16
19
  relying_party: relying_party
17
20
  )
@@ -22,6 +25,7 @@ module WebAuthn
22
25
  id:,
23
26
  raw_id:,
24
27
  response:,
28
+ authenticator_attachment: nil,
25
29
  client_extension_outputs: {},
26
30
  relying_party: WebAuthn.configuration.relying_party
27
31
  )
@@ -29,11 +33,18 @@ module WebAuthn
29
33
  @id = id
30
34
  @raw_id = raw_id
31
35
  @client_extension_outputs = client_extension_outputs
36
+ @authenticator_attachment = authenticator_attachment
32
37
  @response = response
33
38
  @relying_party = relying_party
34
39
  end
35
40
 
36
- def verify(*_args)
41
+ def verify(challenge, *_args)
42
+ unless valid_class?(challenge)
43
+ msg = "challenge must be a String. input challenge class: #{challenge.class}"
44
+
45
+ raise(InvalidChallengeError, msg)
46
+ end
47
+
37
48
  valid_type? || raise("invalid type")
38
49
  valid_id? || raise("invalid id")
39
50
 
@@ -68,6 +79,10 @@ module WebAuthn
68
79
  raw_id && id && raw_id == WebAuthn.standard_encoder.decode(id)
69
80
  end
70
81
 
82
+ def valid_class?(challenge)
83
+ challenge.is_a?(String)
84
+ end
85
+
71
86
  def authenticator_data
72
87
  response&.authenticator_data
73
88
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebAuthn
4
- VERSION = "3.0.0"
4
+ VERSION = "3.1.0"
5
5
  end
data/webauthn.gemspec CHANGED
@@ -42,6 +42,7 @@ Gem::Specification.new do |spec|
42
42
  spec.add_dependency "safety_net_attestation", "~> 0.4.0"
43
43
  spec.add_dependency "tpm-key_attestation", "~> 0.12.0"
44
44
 
45
+ spec.add_development_dependency "base64", ">= 0.1.0"
45
46
  spec.add_development_dependency "bundler", ">= 1.17", "< 3.0"
46
47
  spec.add_development_dependency "byebug", "~> 11.0"
47
48
  spec.add_development_dependency "rake", "~> 13.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.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: 2023-02-15 00:00:00.000000000 Z
12
+ date: 2023-12-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: android_key_attestation
@@ -123,6 +123,20 @@ dependencies:
123
123
  - - "~>"
124
124
  - !ruby/object:Gem::Version
125
125
  version: 0.12.0
126
+ - !ruby/object:Gem::Dependency
127
+ name: base64
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: 0.1.0
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: 0.1.0
126
140
  - !ruby/object:Gem::Dependency
127
141
  name: bundler
128
142
  requirement: !ruby/object:Gem::Requirement
@@ -237,6 +251,7 @@ executables: []
237
251
  extensions: []
238
252
  extra_rdoc_files: []
239
253
  files:
254
+ - ".github/dependabot.yml"
240
255
  - ".github/workflows/build.yml"
241
256
  - ".github/workflows/git.yml"
242
257
  - ".gitignore"
@@ -322,7 +337,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
322
337
  - !ruby/object:Gem::Version
323
338
  version: '0'
324
339
  requirements: []
325
- rubygems_version: 3.2.32
340
+ rubygems_version: 3.4.10
326
341
  signing_key:
327
342
  specification_version: 4
328
343
  summary: WebAuthn ruby server library