devise-passkeys 0.1.0 → 0.2.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: 2447f73b6085c64f92155f7fbef7e0fec400c1d0850e267bd75d0c5f5d1c5131
4
- data.tar.gz: 4574971ab7925b50c8513273c9dd077e09732a22952533c7a92ceabee7071115
3
+ metadata.gz: ad58f89b95e34fd2da78725ca88415708d0bcb9f461b3ced274065782dd6758d
4
+ data.tar.gz: cf5c43539eee37968339470855580544c2a366dd2a09231e55810203369b7116
5
5
  SHA512:
6
- metadata.gz: a0be4cd6b62abe8589b238b09684abaed8a1434cc3377880111dbb521edea92a085fd4d108490bc0bafb0270d642bc1b1426d4141420fce7198aa14e3d7da47c
7
- data.tar.gz: 93752f8ef25cb01502abc1420d6fda0861a43719ab38dfd843b5699ec6f51126668e91da6bc5fce681f94c153c3a64d192b19829657bbedd4945a4f9e68b62ca
6
+ metadata.gz: c59f446a7aaf5e93f9d1e11414f0cdb26c2273e39897d912eb1c63d8852cae8de793b975c9e29583b9c6edb34ba2a300dba9d428d6174411800ad2d1e76acbf5
7
+ data.tar.gz: 60d088c413ed62b9be3254dfc3c9d83a2582c67a382575cdbfabd441135fc7a60e5891d3ecc981a8e4fb9cc00a9be40fe9368372af62e3207ad19c66846d5f78
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown
data/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
- ## [Unreleased]
1
+ ## [0.2.0] - 2023-07-07
2
2
 
3
- ## [0.1.0] - 2022-10-13
3
+ ### Bugfixes
4
+ - Fixed bug with `Devise::Strategies::PasskeyReauthentication` clearing the CSRF token after reauthentication
5
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/45
6
+ - Fixed bug where `RegistrationsControllerConcern` was using `:user` as the Strong Parameters key, rather than `resource_key`
7
+ - https://github.com/ruby-passkeys/devise-passkeys/commit/5ef8c83ffe57b3719ab574a01c710ee3ba7dcfb1
8
+ - Rename `create_resource_and_passkey` => `create_passkey_for_resource`
9
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/37
10
+ - `ReauthenticationControllerConcern` and `SessionsControllerConcern` raise `NoMethodError` if the `relying_party` has not been overridden
11
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/32
12
+
13
+ ### Refactoring
14
+
15
+ - Refactor PasskeysControllerConcern to have clearer credential verify with `verify_credential_integrity`
16
+ -https://github.com/ruby-passkeys/devise-passkeys/pull/29/commits/f1400cb4b217c20b9e74fda3f55f74284e373d25
17
+ - Refactor Controller concerns to not use `Warden::WebAuthn::StrategyHelpers`
18
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/29
19
+ - Rename `Devise::Passkeys::Controllers::Concerns::PasskeyReauthentication` => `Devise::Passkeys::Controllers::Concerns::Reauthentication`
20
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/7/
21
+ - Add `passkey:` keyword param to `after_passkey_authentication` callback
22
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/26
23
+ - Removed unused `:maximum_passkeys_per_user` attribute
24
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/41
25
+
26
+ ### Etc.
27
+ - Bump to warden-webauthn 0.2.1
28
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/29/commits/d825ffded91aa98801bdd5530442761aa60538f9
29
+ - Use `Warden::WebAuthn::RackHelper.set_relying_party_in_request_env` to streamline setup
30
+ https://github.com/ruby-passkeys/devise-passkeys/pull/29/commits/7b7d50129ebe83b0a224d0ace0e4cff8ea407f4a
31
+ - Bump `Devise` requirement to `>= 4.7.1`
32
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/11
33
+ - Documentation
34
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/12
35
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/44
36
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/43
37
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/39
38
+ - https://github.com/ruby-passkeys/devise-passkeys/pull/38
39
+
40
+
41
+ ## [0.1.0] - 2023-05-07
4
42
 
5
43
  - Initial release
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,47 @@
1
+ # Contributing
2
+
3
+ ## Installation
4
+
5
+ After checking out the repo, run the following to install both Bundler and Appraisal dependencies:
6
+
7
+ ```sh
8
+ bin/setup
9
+ ```
10
+
11
+ # Run tests
12
+
13
+ To run the test suite for all Appraisal variants, run:
14
+
15
+ ```sh
16
+ bundle exec appraisal rake test
17
+ ```
18
+
19
+ or
20
+
21
+ ```sh
22
+ bin/test
23
+ ```
24
+
25
+ ## Writing Documentation
26
+
27
+ Documentation is written using [YARD](http://yardoc.org/).
28
+
29
+ You can start a YARD server to view the generated documentation (with automatic reloading) by running:
30
+
31
+ ```sh
32
+ bin/yard
33
+ ```
34
+
35
+ The documentation site will now be available at [http://localhost:8808](http://localhost:8808)
36
+
37
+ ## Interactive Console
38
+
39
+ You can also run the following for an interactive prompt that will allow you to experiment:
40
+
41
+ ```sh
42
+ bin/console
43
+ ```
44
+
45
+ # Gem installation & cutting
46
+
47
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
data/Gemfile CHANGED
@@ -10,6 +10,8 @@ group :development, :test do
10
10
  gem "debug"
11
11
  gem "rake", "~> 13.0"
12
12
  gem "rubocop", "~> 1.21"
13
+ gem 'yard'
14
+ gem 'webrick'
13
15
  end
14
16
 
15
17
  group :test do
data/Gemfile.lock CHANGED
@@ -1,19 +1,32 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- devise-passkeys (0.1.0)
5
- devise
6
- warden-webauthn (>= 0.2.0)
4
+ devise-passkeys (0.2.0)
5
+ devise (>= 4.7.1)
6
+ warden-webauthn (>= 0.2.1)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activemodel (7.0.4.2)
12
- activesupport (= 7.0.4.2)
13
- activerecord (7.0.4.2)
14
- activemodel (= 7.0.4.2)
15
- activesupport (= 7.0.4.2)
16
- activesupport (7.0.4.2)
11
+ actionpack (7.0.6)
12
+ actionview (= 7.0.6)
13
+ activesupport (= 7.0.6)
14
+ rack (~> 2.0, >= 2.2.4)
15
+ rack-test (>= 0.6.3)
16
+ rails-dom-testing (~> 2.0)
17
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
18
+ actionview (7.0.6)
19
+ activesupport (= 7.0.6)
20
+ builder (~> 3.1)
21
+ erubi (~> 1.4)
22
+ rails-dom-testing (~> 2.0)
23
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
24
+ activemodel (7.0.6)
25
+ activesupport (= 7.0.6)
26
+ activerecord (7.0.6)
27
+ activemodel (= 7.0.6)
28
+ activesupport (= 7.0.6)
29
+ activesupport (7.0.6)
17
30
  concurrent-ruby (~> 1.0, >= 1.0.2)
18
31
  i18n (>= 1.6, < 2)
19
32
  minitest (>= 5.1)
@@ -25,16 +38,16 @@ GEM
25
38
  thor (>= 0.14.0)
26
39
  ast (2.4.2)
27
40
  awrence (1.2.1)
28
- bcrypt (3.1.18)
29
- bcrypt-ruby (3.1.5)
30
- bcrypt (>= 3.1.3)
41
+ bcrypt (3.1.19)
31
42
  bindata (2.4.15)
32
43
  bson (4.15.0)
44
+ builder (3.2.4)
33
45
  cbor (0.5.9.6)
34
- concurrent-ruby (1.2.0)
46
+ concurrent-ruby (1.2.2)
35
47
  cose (1.3.0)
36
48
  cbor (~> 0.5.9)
37
49
  openssl-signature_algorithm (~> 1.0)
50
+ crass (1.0.6)
38
51
  database_cleaner-active_record (2.1.0)
39
52
  activerecord (>= 5.a)
40
53
  database_cleaner-core (~> 2.0.0)
@@ -42,61 +55,95 @@ GEM
42
55
  database_cleaner-mongoid (2.0.1)
43
56
  database_cleaner-core (~> 2.0.0)
44
57
  mongoid
45
- debug (1.7.1)
58
+ debug (1.8.0)
46
59
  irb (>= 1.5.0)
47
60
  reline (>= 0.3.1)
48
- devise (1.5.4)
49
- bcrypt-ruby (~> 3.0)
50
- orm_adapter (~> 0.0.3)
51
- warden (~> 1.1)
61
+ devise (4.9.2)
62
+ bcrypt (~> 3.0)
63
+ orm_adapter (~> 0.1)
64
+ railties (>= 4.1.0)
65
+ responders
66
+ warden (~> 1.2.3)
52
67
  docile (1.4.0)
53
- i18n (1.12.0)
68
+ erubi (1.12.0)
69
+ i18n (1.14.1)
54
70
  concurrent-ruby (~> 1.0)
55
71
  io-console (0.6.0)
56
- irb (1.6.2)
72
+ irb (1.7.1)
57
73
  reline (>= 0.3.0)
58
74
  json (2.6.3)
59
- jwt (2.7.0)
75
+ jwt (2.7.1)
76
+ language_server-protocol (3.17.0.3)
77
+ loofah (2.21.3)
78
+ crass (~> 1.0.2)
79
+ nokogiri (>= 1.12.0)
60
80
  m (1.6.1)
61
81
  method_source (>= 0.6.7)
62
82
  rake (>= 0.9.2.2)
63
83
  method_source (1.0.0)
64
- minitest (5.17.0)
84
+ minitest (5.18.1)
65
85
  minitest-ci (3.4.0)
66
86
  minitest (>= 5.0.6)
67
- mongo (2.18.2)
87
+ mongo (2.19.0)
68
88
  bson (>= 4.14.1, < 5.0.0)
69
- mongoid (8.0.3)
89
+ mongoid (8.1.0)
70
90
  activemodel (>= 5.1, < 7.1, != 7.0.0)
91
+ concurrent-ruby (>= 1.0.5, < 2.0)
71
92
  mongo (>= 2.18.0, < 3.0.0)
72
93
  ruby2_keywords (~> 0.0.5)
94
+ nokogiri (1.15.3-arm64-darwin)
95
+ racc (~> 1.4)
96
+ nokogiri (1.15.3-x86_64-linux)
97
+ racc (~> 1.4)
73
98
  openssl (3.1.0)
74
99
  openssl-signature_algorithm (1.3.0)
75
100
  openssl (> 2.0)
76
- orm_adapter (0.0.7)
77
- parallel (1.22.1)
78
- parser (3.2.1.0)
101
+ orm_adapter (0.5.0)
102
+ parallel (1.23.0)
103
+ parser (3.2.2.3)
79
104
  ast (~> 2.4.1)
80
- rack (3.0.4.1)
105
+ racc
106
+ racc (1.7.1)
107
+ rack (2.2.7)
108
+ rack-test (2.1.0)
109
+ rack (>= 1.3)
110
+ rails-dom-testing (2.1.1)
111
+ activesupport (>= 5.0.0)
112
+ minitest
113
+ nokogiri (>= 1.6)
114
+ rails-html-sanitizer (1.6.0)
115
+ loofah (~> 2.21)
116
+ nokogiri (~> 1.14)
117
+ railties (7.0.6)
118
+ actionpack (= 7.0.6)
119
+ activesupport (= 7.0.6)
120
+ method_source
121
+ rake (>= 12.2)
122
+ thor (~> 1.0)
123
+ zeitwerk (~> 2.5)
81
124
  rainbow (3.1.1)
82
125
  rake (13.0.6)
83
- regexp_parser (2.7.0)
84
- reline (0.3.2)
126
+ regexp_parser (2.8.1)
127
+ reline (0.3.5)
85
128
  io-console (~> 0.5)
129
+ responders (3.1.0)
130
+ actionpack (>= 5.2)
131
+ railties (>= 5.2)
86
132
  rexml (3.2.5)
87
- rubocop (1.45.1)
133
+ rubocop (1.54.1)
88
134
  json (~> 2.3)
135
+ language_server-protocol (>= 3.17.0)
89
136
  parallel (~> 1.10)
90
- parser (>= 3.2.0.0)
137
+ parser (>= 3.2.2.3)
91
138
  rainbow (>= 2.2.2, < 4.0)
92
139
  regexp_parser (>= 1.8, < 3.0)
93
140
  rexml (>= 3.2.5, < 4.0)
94
- rubocop-ast (>= 1.24.1, < 2.0)
141
+ rubocop-ast (>= 1.28.0, < 2.0)
95
142
  ruby-progressbar (~> 1.7)
96
143
  unicode-display_width (>= 2.4.0, < 3.0)
97
- rubocop-ast (1.26.0)
144
+ rubocop-ast (1.29.0)
98
145
  parser (>= 3.2.1.0)
99
- ruby-progressbar (1.11.0)
146
+ ruby-progressbar (1.13.0)
100
147
  ruby2_keywords (0.0.5)
101
148
  safety_net_attestation (0.4.0)
102
149
  jwt (~> 2.0)
@@ -106,7 +153,7 @@ GEM
106
153
  simplecov_json_formatter (~> 0.1)
107
154
  simplecov-html (0.12.3)
108
155
  simplecov_json_formatter (0.1.4)
109
- thor (1.2.1)
156
+ thor (1.2.2)
110
157
  tpm-key_attestation (0.12.0)
111
158
  bindata (~> 2.4)
112
159
  openssl (> 2.0)
@@ -116,7 +163,7 @@ GEM
116
163
  unicode-display_width (2.4.2)
117
164
  warden (1.2.9)
118
165
  rack (>= 2.0.9)
119
- warden-webauthn (0.2.0)
166
+ warden-webauthn (0.2.1)
120
167
  warden
121
168
  webauthn (>= 3)
122
169
  webauthn (3.0.0)
@@ -128,6 +175,9 @@ GEM
128
175
  openssl (>= 2.2)
129
176
  safety_net_attestation (~> 0.4.0)
130
177
  tpm-key_attestation (~> 0.12.0)
178
+ webrick (1.8.1)
179
+ yard (0.9.34)
180
+ zeitwerk (2.6.8)
131
181
 
132
182
  PLATFORMS
133
183
  arm64-darwin-21
@@ -146,6 +196,8 @@ DEPENDENCIES
146
196
  rake (~> 13.0)
147
197
  rubocop (~> 1.21)
148
198
  simplecov
199
+ webrick
200
+ yard
149
201
 
150
202
  BUNDLED WITH
151
- 2.3.7
203
+ 2.4.12
data/README.md CHANGED
@@ -19,7 +19,7 @@ $ bundle
19
19
 
20
20
  # Usage
21
21
 
22
- 1. Add `:passkey_authenticatable` in your Devise-enabled model
22
+ ## Add `:passkey_authenticatable`
23
23
 
24
24
  ```ruby
25
25
  class User < ApplicationRecord
@@ -35,7 +35,7 @@ class User < ApplicationRecord
35
35
  self.find_by(id: passkey.user.id)
36
36
  end
37
37
 
38
- def after_passkey_authentication
38
+ def after_passkey_authentication(passkey:)
39
39
  end
40
40
  end
41
41
  ```
@@ -47,7 +47,7 @@ The Devise-enabled model must have a `webauthn_id` field in the model; which is:
47
47
 
48
48
  This will allow you to explictly establish the relationship between a user & its passkeys (to help both your app & the user's authenticator with credential management)
49
49
 
50
- 2. Generate the model that will store passkeys. The model name is not important, but the Devise-enabled model should have:
50
+ ## Generate the Model That Will Store Passkeys. Should Have:
51
51
  - A `has_many :passkeys` association
52
52
  - A `passkey_class` class method that returns the passkey class
53
53
  - A `find_for_passkey(passkey)` class method that finds the user for a given passkey
@@ -66,7 +66,7 @@ The following fields are required:
66
66
 
67
67
  It's recommended to add unique indexes on `external_id` and `public_key`
68
68
 
69
- 3. Generate custom devise controllers & views for your Devise-enabled model
69
+ ## Generate Custom Devise Controllers & Views
70
70
 
71
71
  [Since Devise does not have built-in passkeys support yet](https://github.com/heartcombo/devise/issues/5527), you'll need to customize both the controllers & the views
72
72
 
@@ -77,7 +77,7 @@ rails generate devise:views users
77
77
 
78
78
  If you're trying to keep your codebase small, these instructions only concern the `Users::SessionsController` & `Users::RegistrationsController`, so you can delete any other generated custom controllers if needed. You will likely need to modify the `views/users/shared/*` partials though, because they assume passwords are being used.
79
79
 
80
- 4. Include the passkeys concerns into your controllers
80
+ ## Include the Passkeys Concerns in Your Controllers
81
81
 
82
82
  Rather than having base classes, `Devise::Passkeys` has a series of concerns that can be mixed into your controllers. This allows you to change behavior, and does not keep you stuck down a path that could be incompatible with your existing authentication setup.
83
83
 
@@ -96,10 +96,6 @@ class Users::SessionsController < Devise::SessionsController
96
96
  def relying_party
97
97
  WebAuthn::RelyingParty.new(...)
98
98
  end
99
-
100
- def set_relying_party_in_request_env
101
- request.env[relying_party_key] = relying_party
102
- end
103
99
  end
104
100
 
105
101
  # frozen_string_literal: true
@@ -111,10 +107,6 @@ class Users::ReauthenticationController < DeviseController
111
107
  def relying_party
112
108
  WebAuthn::RelyingParty.new(...)
113
109
  end
114
-
115
- def set_relying_party_in_request_env
116
- request.env[relying_party_key] = relying_party
117
- end
118
110
  end
119
111
 
120
112
  # frozen_string_literal: true
@@ -126,15 +118,11 @@ class Users::PasskeysController < DeviseController
126
118
  def relying_party
127
119
  WebAuthn::RelyingParty.new(...)
128
120
  end
129
-
130
- def set_relying_party_in_request_env
131
- request.env[relying_party_key] = relying_party
132
- end
133
121
  end
134
122
 
135
123
  ```
136
124
 
137
- 6. Add necessary routes
125
+ ## Add Routes
138
126
 
139
127
  Given the customization routes usually require, you'll need to hook up the routes yourself. Here's an example:
140
128
 
@@ -165,6 +153,22 @@ devise_scope :user do
165
153
  end
166
154
  ```
167
155
 
156
+ ## Reimplement the `:passkey_authenticatable` Module
157
+
158
+ **Important**: You will need to reimplement the `:passkey_authenticatable` Devise module. This will override the module definition with your implementation specific definitions; pointing to the specific route, controller, etc.
159
+
160
+ Here's an example from [devise-passkeys-template](https://github.com/ruby-passkeys/devise-passkeys-template/blob/main/app/models/user.rb#L18):
161
+
162
+ ```ruby
163
+ Devise.add_module :passkey_authenticatable,
164
+ model: 'devise/passkeys/model',
165
+ route: {session: [nil, :new, :create, :destroy] },
166
+ controller: 'controller/sessions',
167
+ strategy: true,
168
+ no_input: true
169
+ ```
170
+
171
+ # FAQs
168
172
 
169
173
  ## What about the Webauthn javascript? Mailers? Error handling?
170
174
 
@@ -176,13 +180,11 @@ Here's a template repo! https://github.com/ruby-passkeys/devise-passkeys-templat
176
180
 
177
181
  ## Development
178
182
 
179
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
180
-
181
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
183
+ Please see [CONTRIBUTING.md](https://github.com/ruby-passkeys/devise-passkeys/blob/main/CONTRIBUTING.md) for guidance on how to help out!
182
184
 
183
185
  ## Contributing
184
186
 
185
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/devise-passkeys. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/devise-passkeys/blob/main/CODE_OF_CONDUCT.md).
187
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby-passkeys/devise-passkeys. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/ruby-passkeys/devise-passkeys/blob/main/CODE_OF_CONDUCT.md).
186
188
 
187
189
  ## License
188
190
 
@@ -190,7 +192,7 @@ The gem is available as open source under the terms of the [MIT License](https:/
190
192
 
191
193
  ## Code of Conduct
192
194
 
193
- Everyone interacting in the Devise::Passkeys project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/devise-passkeys/blob/main/CODE_OF_CONDUCT.md).
195
+ Everyone interacting in the Devise::Passkeys project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/ruby-passkeys/devise-passkeys/blob/main/CODE_OF_CONDUCT.md).
194
196
 
195
197
 
196
198
  ## Acknowledgements
data/THANKS.md ADDED
@@ -0,0 +1,9 @@
1
+ # Thanks to everyone's who's contributed or helped out!
2
+
3
+ ## Contributors
4
+
5
+ - [@heliocola](https://github.com/heliocola)
6
+ - [@JanaganSaravanan](https://github.com/JanaganSaravanan)
7
+ - [@johalloran01](https://github.com/johalloran01)
8
+ - [@tcannonfodder](https://github.com/tcannonfodder)
9
+ - [@Vagab](https://github.com/Vagab)
@@ -32,8 +32,8 @@ Gem::Specification.new do |spec|
32
32
  spec.require_paths = ["lib"]
33
33
 
34
34
  # Uncomment to register a new dependency of your gem
35
- spec.add_dependency "devise"
36
- spec.add_dependency "warden-webauthn", ">= 0.2.0"
35
+ spec.add_dependency "devise", ">= 4.7.1"
36
+ spec.add_dependency "warden-webauthn", ">= 0.2.1"
37
37
 
38
38
  # For more information and examples about making a new gem, check out our
39
39
  # guide at: https://bundler.io/guides/creating_gem.html
@@ -10,6 +10,8 @@ group :development, :test do
10
10
  gem "debug"
11
11
  gem "rake", "~> 13.0"
12
12
  gem "rubocop", "~> 1.21"
13
+ gem "yard"
14
+ gem "webrick"
13
15
  end
14
16
 
15
17
  group :test do
@@ -10,6 +10,8 @@ group :development, :test do
10
10
  gem "debug"
11
11
  gem "rake", "~> 13.0"
12
12
  gem "rubocop", "~> 1.21"
13
+ gem "yard"
14
+ gem "webrick"
13
15
  end
14
16
 
15
17
  group :test do
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Devise
4
+ module Passkeys
5
+ module Controllers
6
+ module Concerns
7
+ # This concern is responsible for storing, retrieving, clearing, consuming,
8
+ # and validating the reauthentication token in the session.
9
+ #
10
+ # A reauthentication token is a one-time random value that is used to
11
+ # indicate that the user has successfully been reauthenticated. This can be
12
+ # used for scenarios such as:
13
+ #
14
+ # - Adding a new passkey
15
+ # - Deleting a passkey
16
+ # - Performing sensitive actions inside your application
17
+ #
18
+ # You can customize which reauthentication token you're using by changing
19
+ # the `passkey_reauthentication_token_key` method after including this concern
20
+ #
21
+ # @see Devise::Passkeys::Controllers::ReauthenticationControllerConcern
22
+ module Reauthentication
23
+ extend ActiveSupport::Concern
24
+
25
+ # This method is responsible for storing the reauthentication token
26
+ # in the session.
27
+ #
28
+ # The reauthentication token is securely generated using `Devise.friendly_token`
29
+ #
30
+ # @return [String] The reauthentication token
31
+ # @see passkey_reauthentication_token_key
32
+ def store_reauthentication_token_in_session
33
+ session[passkey_reauthentication_token_key] = Devise.friendly_token(50)
34
+ end
35
+
36
+ # This method is responsible for retrieving the reauthentication token
37
+ # from the session.
38
+ #
39
+ # @return [String] The reauthentication token
40
+ # @see passkey_reauthentication_token_key
41
+ # @see store_reauthentication_token_in_session
42
+ def stored_reauthentication_token
43
+ session[passkey_reauthentication_token_key]
44
+ end
45
+
46
+ # This method is responsible for clearing the reauthentication token from
47
+ # the session.
48
+ #
49
+ # @return [String] The reauthentication token
50
+ # @see passkey_reauthentication_token_key
51
+ def clear_reauthentication_token!
52
+ session.delete(passkey_reauthentication_token_key)
53
+ end
54
+
55
+ # This method is responsible for consuming (i.e. retrieving & clearing)
56
+ # the reauthentication token from the session.
57
+ #
58
+ # @return [String] The reauthentication token
59
+ # @see stored_reauthentication_token
60
+ # @see clear_reauthentication_token!
61
+ def consume_reauthentication_token!
62
+ value = stored_reauthentication_token
63
+ clear_reauthentication_token!
64
+ value
65
+ end
66
+
67
+ # This method is responsible for validating the given reauthentication token
68
+ # against the one currently in the session.
69
+ #
70
+ # **Note**: Whenever a reauthentication token is checked using `valid_reauthentication_token?`,
71
+ # It will be consumed. This means that a new token will need to be generated & stored
72
+ # (by reauthenticating the user) if there were any issues.
73
+ #
74
+ # @param [String] given_reauthentication_token token to compare store token against
75
+ # @return [Boolean] whether the `given_reauthentication_token` is the same as the
76
+ # `stored_reauthentication_token`
77
+ # @see consume_reauthentication_token!
78
+ def valid_reauthentication_token?(given_reauthentication_token:)
79
+ Devise.secure_compare(consume_reauthentication_token!, given_reauthentication_token)
80
+ end
81
+
82
+ # This method is responsible for generating the key that will be used
83
+ # to store the reauthentication token in the session hash.
84
+ #
85
+ # @return [String] The key that will be used to access the reauthentication token in the session
86
+ def passkey_reauthentication_token_key
87
+ "#{resource_name}_current_reauthentication_token"
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -4,13 +4,39 @@ module Devise
4
4
  module Passkeys
5
5
  module Controllers
6
6
  module Concerns
7
+ # This concern is responsible for storing the reauthentication challenge in the session.
8
+ #
9
+ # A reauthentication challenge is a WebAuthn challenge exchange (i.e. authentication)
10
+ # to verify the user's identity and confirm they're able to perform a sensitive action
11
+ # by performing the entire authentication process.
12
+ #
13
+ # This can be used for scenarios such as:
14
+ #
15
+ # - Adding a new passkey
16
+ # - Deleting a passkey
17
+ # - Performing sensitive actions inside your application
18
+ #
19
+ # You can customize which reauthentication challenge you're using by changing
20
+ # the `passkey_reauthentication_challenge_session_key` method after including this concern
21
+ #
22
+ # @see Devise::Passkeys::Controllers::ReauthenticationControllerConcern
7
23
  module ReauthenticationChallenge
8
24
  extend ActiveSupport::Concern
9
25
 
26
+ # This method is responsible for generating the key that will be used to store the
27
+ # reauthentication challenge in the session hash.
28
+ #
29
+ # @return [String] The reauthentication challenge session key
10
30
  def passkey_reauthentication_challenge_session_key
11
31
  "#{resource_name}_current_reauthentication_challenge"
12
32
  end
13
33
 
34
+ # This method is responsible for storing the reauthentication challenge in the session.
35
+ #
36
+ # @param [WebAuthn::PublicKeyCredential::RequestOptions] options_for_authentication the options for authentication,
37
+ # generated by `webauthn-ruby`
38
+ # @return [String] The reauthentication challenge
39
+ # @see Devise::Passkeys::Controllers::ReauthenticationControllerConcern#new_challenge
14
40
  def store_reauthentication_challenge_in_session(options_for_authentication:)
15
41
  session[passkey_reauthentication_challenge_session_key] = options_for_authentication.challenge
16
42
  end