devise-passkeys 0.1.0 → 0.3.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.
@@ -7,16 +7,16 @@ module Devise
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
- include Devise::Passkeys::Controllers::Concerns::PasskeyReauthentication
10
+ include Devise::Passkeys::Controllers::Concerns::Reauthentication
11
11
  include Devise::Passkeys::Controllers::Concerns::ReauthenticationChallenge
12
12
  include Warden::WebAuthn::AuthenticationInitiationHelpers
13
13
  include Warden::WebAuthn::RegistrationHelpers
14
- include Warden::WebAuthn::StrategyHelpers
15
14
 
16
15
  prepend_before_action :authenticate_scope!
17
16
  before_action :ensure_at_least_one_passkey, only: %i[new_destroy_challenge destroy]
18
17
  before_action :find_passkey, only: %i[new_destroy_challenge destroy]
19
18
 
19
+ before_action :verify_credential_integrity, only: [:create]
20
20
  before_action :verify_passkey_challenge, only: [:create]
21
21
  before_action :verify_reauthentication_token, only: %i[create destroy]
22
22
 
@@ -93,18 +93,17 @@ module Devise
93
93
  { id: resource.webauthn_id, name: resource.email }
94
94
  end
95
95
 
96
+ def verify_credential_integrity
97
+ return render_credential_missing_or_could_not_be_parsed_error if parsed_credential.nil?
98
+ rescue JSON::JSONError, TypeError
99
+ return render_credential_missing_or_could_not_be_parsed_error
100
+ end
101
+
96
102
  def verify_passkey_challenge
97
- if parsed_credential.nil?
98
- render json: { message: find_message(:credential_missing_or_could_not_be_parsed) }, status: :bad_request
99
- delete_registration_challenge
100
- return false
101
- end
102
- begin
103
- @webauthn_credential = verify_registration(relying_party: relying_party)
104
- rescue ::WebAuthn::Error => e
105
- error_key = Warden::WebAuthn::ErrorKeyFinder.webauthn_error_key(exception: e)
106
- render json: { message: find_message(error_key) }, status: :bad_request
107
- end
103
+ @webauthn_credential = verify_registration(relying_party: relying_party)
104
+ rescue ::WebAuthn::Error => e
105
+ error_key = Warden::WebAuthn::ErrorKeyFinder.webauthn_error_key(exception: e)
106
+ render json: { message: find_message(error_key) }, status: :bad_request
108
107
  end
109
108
 
110
109
  def passkey_params
@@ -134,6 +133,12 @@ module Devise
134
133
  def reauthentication_params
135
134
  params.require(:passkey).permit(:reauthentication_token)
136
135
  end
136
+
137
+ def render_credential_missing_or_could_not_be_parsed_error
138
+ render json: { message: find_message(:credential_missing_or_could_not_be_parsed) }, status: :bad_request
139
+ delete_registration_challenge
140
+ return false
141
+ end
137
142
  end
138
143
  end
139
144
  end
@@ -3,14 +3,44 @@
3
3
  module Devise
4
4
  module Passkeys
5
5
  module Controllers
6
+ # This concern is responsible for handling reauthentication.
7
+ # It should be included in any controller that handles reauthentication, and defines:
8
+ #
9
+ # - Useful methods to assist with the reauthentication process
10
+ # - Concerns that are required to complete the reauthentication process
11
+ # - Helper modules from `Warden::WebAuthn` that are required to complete the reauthentication process
12
+ #
13
+ # **Note**: the implementing controller **must** define a `relying_party` method in order for
14
+ # reauthentications to work.
15
+ #
16
+ # @example
17
+ # class ReauthenticationController < ApplicationController
18
+ # include Devise::Passkeys::Controllers::ReauthenticationControllerConcern
19
+ #
20
+ # def relying_party
21
+ # WebAuthn::RelyingParty.new
22
+ # end
23
+ # end
24
+ #
25
+ # The `authenticate_scope!` is called as a `before_action` to verify the authentication and set the
26
+ # `resource` for the controller.
27
+ #
28
+ # Likewise, `Warden::WebAuthn::RackHelpers#set_relying_party_in_request_env` is a `before_action` to ensure that the relying party is set in the
29
+ # `request.env` before the Warden strategy is executed
30
+ #
31
+ # @see relying_party
32
+ # @see Devise::Passkeys::Controllers::Concerns::ReauthenticationChallenge
33
+ # @see Devise::Passkeys::Controllers::Concerns::Reauthentication
34
+ # @see Warden::WebAuthn::StrategyHelpers
35
+ # @see Warden::WebAuthn::RackHelpers
6
36
  module ReauthenticationControllerConcern
7
37
  extend ActiveSupport::Concern
8
38
 
9
39
  included do
10
- include Devise::Passkeys::Controllers::Concerns::PasskeyReauthentication
40
+ include Devise::Passkeys::Controllers::Concerns::Reauthentication
11
41
  include Devise::Passkeys::Controllers::Concerns::ReauthenticationChallenge
12
42
  include Warden::WebAuthn::AuthenticationInitiationHelpers
13
- include Warden::WebAuthn::StrategyHelpers
43
+ include Warden::WebAuthn::RackHelpers
14
44
 
15
45
  prepend_before_action :authenticate_scope!
16
46
 
@@ -27,6 +57,14 @@ module Devise
27
57
  end
28
58
  end
29
59
 
60
+ # A controller action that stores the reauthentication challenge in session
61
+ # and renders the options for authentication from `webauthn-ruby`.
62
+ #
63
+ # The response is rendered as JSON, with a status of `200 OK`.
64
+ #
65
+ # @see Devise::Passkeys::Controllers::Concerns::ReauthenticationChallenge#store_reauthentication_challenge_in_session
66
+ # @see Warden::WebAuthn::AuthenticationInitiationHelpers#generate_authentication_options
67
+ # @see Warden::WebAuthn::RackHelpers#set_relying_party_in_request_env
30
68
  def new_challenge
31
69
  options_for_authentication = generate_authentication_options(relying_party: relying_party,
32
70
  options: { allow: resource.passkeys.pluck(:external_id) })
@@ -36,6 +74,24 @@ module Devise
36
74
  render json: options_for_authentication
37
75
  end
38
76
 
77
+ # A controller action that:
78
+ #
79
+ # 1. Uses the `warden` strategy to authenticate the current user with the defined strategy
80
+ # 2. Calls `sign_in` with `event: :passkey_reauthentication` to verify that the user can authenticate
81
+ # 3. Stores the reauthentication token in the session
82
+ # 4. Renders a JSON object with the reauthentication token
83
+ # 5. Ensures that the reauthentication challenge from the session, regardless of any errors
84
+ #
85
+ # @example
86
+ # {"reauthentication_token": "abcd1234"}
87
+ #
88
+ # `prepare_params` is called as a `before_action` to prepare the passkey credential for use by the
89
+ # Warden strategy.
90
+ #
91
+ # Optionally accepts a block that will be executed after the user has been reauthenticated.
92
+ # @see strategy
93
+ # @see Devise::Passkeys::Controllers::Concerns::Reauthentication#store_reauthentication_token_in_session
94
+ # @see prepare_params
39
95
  def reauthenticate
40
96
  sign_out(resource)
41
97
  self.resource = warden.authenticate!(strategy, auth_options)
@@ -51,12 +107,18 @@ module Devise
51
107
 
52
108
  protected
53
109
 
110
+ # @!visibility public
111
+ # Prepares the request parameters for use by the Warden strategy
54
112
  def prepare_params
55
113
  request.params[resource_name] = ActionController::Parameters.new({
56
114
  passkey_credential: params[:passkey_credential]
57
115
  })
58
116
  end
59
117
 
118
+ # @!visibility public
119
+ # A method that can be overridden to customize the Warden stratey used.
120
+ # @return [Symbol] The key that identifies which `Warden` strategy will be used to handle the
121
+ # authentication flow for the reauthentication. Defaults to `:passkey_reauthentication`
60
122
  def strategy
61
123
  :passkey_reauthentication
62
124
  end
@@ -69,8 +131,12 @@ module Devise
69
131
  session.delete(passkey_reauthentication_challenge_session_key)
70
132
  end
71
133
 
72
- def set_relying_party_in_request_env
73
- raise "need to define relying_party for this SessionsController"
134
+ # @!visibility public
135
+ # @abstract
136
+ # The method that returns the `WebAuthn::RelyingParty` for this request.
137
+ # @return [WebAuthn::RelyingParty] when overridden, this method should return a `WebAuthn::RelyingParty` instance
138
+ def relying_party
139
+ raise NoMethodError, "need to define relying_party for this #{self.class.name}"
74
140
  end
75
141
  end
76
142
  end
@@ -3,11 +3,43 @@
3
3
  module Devise
4
4
  module Passkeys
5
5
  module Controllers
6
+ # This concern should be included in any controller that handles
7
+ # user (`resource`) registration management (ie: signup/deleting an account),
8
+ # and defines:
9
+ #
10
+ # - Useful methods and before filters to streamline user (`resource`) registration management using session variables
11
+ # - Controller actions for:
12
+ # - Issuing a new WebAuthn challenge
13
+ # - A `create` action that creates a passkey if the user (`resource`) has been persisted
14
+ # - Helper modules from `Warden::WebAuthn` that are required to complete the registration process
15
+ #
16
+ # The `registration_user_id_key` and `registration_challenge_key` are defined
17
+ # using the `resource_name`, to keep the generated IDs unique between resources
18
+ # during the registration process.
19
+ #
20
+ # A `raw_credential` method is provided to streamline access to
21
+ # `passkey_params[:passkey_credential]`.
22
+ #
23
+ # **Note**: the implementing controller **must** define a `relying_party` method in order for
24
+ # registrations to work.
25
+ #
26
+ # @example
27
+ # class RegistrationsController < ApplicationController
28
+ # include Devise::Passkeys::Controllers::RegistrationsControllerConcern
29
+ #
30
+ # def relying_party
31
+ # WebAuthn::RelyingParty.new
32
+ # end
33
+ # end
34
+ #
35
+ #
36
+ # @see Devise::Passkeys::Controllers::Concerns::Reauthentication
37
+ # @see Warden::WebAuthn::RegistrationHelpers
6
38
  module RegistrationsControllerConcern
7
39
  extend ActiveSupport::Concern
8
40
 
9
41
  included do
10
- include Devise::Passkeys::Controllers::Concerns::PasskeyReauthentication
42
+ include Devise::Passkeys::Controllers::Concerns::Reauthentication
11
43
  include Warden::WebAuthn::RegistrationHelpers
12
44
 
13
45
  before_action :require_no_authentication, only: [:new_challenge]
@@ -30,6 +62,20 @@ module Devise
30
62
  end
31
63
  end
32
64
 
65
+ # This controller action issues a new challenge for the registration handshake.
66
+ #
67
+ # The challenge is stored in a session variable, and renders the WebAuthn
68
+ # registration options as a JSON response.
69
+ #
70
+ # The following before filters are called:
71
+ #
72
+ # - `require_no_authentication`
73
+ # - `require_email_and_passkey_label`
74
+ #
75
+ # @see DeviseController#require_no_authentication
76
+ # @see require_email_and_passkey_label
77
+ # @see Warden::WebAuthn#generate_registration_options
78
+ # @see https://github.com/cedarcode/webauthn-ruby#initiation-phase
33
79
  def new_challenge
34
80
  options_for_registration = generate_registration_options(
35
81
  relying_party: relying_party,
@@ -42,15 +88,48 @@ module Devise
42
88
  render json: options_for_registration
43
89
  end
44
90
 
91
+ # This controller action creates a new user (`resource`), using the given
92
+ # email & passkey. It:
93
+ #
94
+ # 1. calls the parent class's `#create` method
95
+ # 2. calls `#create_passkey_for_resource` to finish creating the passkey
96
+ # if the user (`resource`) was actually persisted
97
+ # 3. Finishes the rest of the parent class's `#create` method
98
+ #
99
+ #
100
+ # The following before actions are called:
101
+ #
102
+ # - `require_email_and_passkey_label`
103
+ # - `verify_passkey_registration_challenge`
104
+ # - `configure_sign_up_params`
105
+ #
106
+ # @see require_email_and_passkey_label
107
+ # @see verify_passkey_registration_challenge
108
+ # @see configure_sign_up_params
109
+ # @see create_passkey_for_resource
45
110
  def create
46
111
  super do |resource|
47
- create_resource_and_passkey(resource: resource)
112
+ create_passkey_for_resource(resource: resource)
48
113
  end
49
114
  end
50
115
 
51
116
  protected
52
117
 
53
- def create_resource_and_passkey(resource:)
118
+ # @!visibility public
119
+ #
120
+ # Creates a passkey for given user (`resource`).
121
+ #
122
+ # The method tests that the user (`resource`) is in the database
123
+ # before saving the passkey for the given user (`resource`).
124
+ #
125
+ #
126
+ # This method also ensures that the generated WebAuthn User ID is deleted from the session to prevent
127
+ # data leaks.
128
+ #
129
+ #
130
+ # @yield [resource, passkey] The provided `resource` and the newly created passkey.
131
+ # @see create_passkey
132
+ def create_passkey_for_resource(resource:)
54
133
  return unless resource.persisted?
55
134
 
56
135
  passkey = create_passkey(resource: resource)
@@ -59,6 +138,17 @@ module Devise
59
138
  delete_registration_user_id!
60
139
  end
61
140
 
141
+ # @!visibility public
142
+ #
143
+ # Generates a passkey for the given `resource`, using the `resource.passkeys.create!`
144
+ # method with the following attributes:
145
+ #
146
+ # - `label`: The `passkey_params[:passkey_label]`
147
+ # - `public_key`: The `@webauthn_credential.public_key`
148
+ # - `external_id`: The credential ID, strictly encoded as a Base 64 string
149
+ # - `sign_count`: The `@webauthn_credential.sign_count`
150
+ # - `last_used_at`: The current time, since this is the first time the passkey is being used
151
+ #
62
152
  def create_passkey(resource:)
63
153
  resource.passkeys.create!(
64
154
  label: passkey_params[:passkey_label],
@@ -69,29 +159,61 @@ module Devise
69
159
  )
70
160
  end
71
161
 
162
+ # @!visibility public
163
+ #
164
+ # Verifies that the given reauthentication token matches the
165
+ # expected value stored in the session.
166
+ #
167
+ # If the reauthentication token is not valid,
168
+ # a `400 Bad Request` JSON response is rendered.
169
+ #
170
+ # @example
171
+ # {"error": "Please reauthenticate to continue."}
172
+ #
173
+ # @see reauthentication_params
174
+ # @see Devise::Passkeys::Controllers::Concerns::Reauthentication#valid_reauthentication_token?
72
175
  def verify_reauthentication_token
73
176
  return if valid_reauthentication_token?(given_reauthentication_token: reauthentication_params[:reauthentication_token])
74
177
 
75
178
  render json: { error: find_message(:not_reauthenticated) }, status: :bad_request
76
179
  end
77
180
 
181
+ # @!visibility public
182
+ # The subset of parameters used when verifying a reauthentication_token
78
183
  def reauthentication_params
79
- params.require(:user).permit(:reauthentication_token)
184
+ params.require(resource_name).permit(:reauthentication_token)
80
185
  end
81
186
 
187
+ # @!visibility public
188
+ # An override of `DeviseController`'s implementation, to circumvent the
189
+ # `update_with_password` method
190
+ # @see DeviseController#update_resource
82
191
  def update_resource(resource, params)
83
192
  resource.update(params)
84
193
  end
85
194
 
86
- # Override if you need to exclude certain external IDs
195
+ # @!visibility public
196
+ # Override this method if you need to exclude certain WebAuthn credentials
197
+ # from a registration request.
198
+ # @see new_challenge
199
+ # @see https://github.com/cedarcode/webauthn-ruby#initiation-phase
87
200
  def exclude_external_ids_for_registration
88
201
  []
89
202
  end
90
203
 
204
+ # @!visibility public
205
+ # The subset of parameters used when verifying the passkey
91
206
  def passkey_params
92
207
  params.require(resource_name).permit(:passkey_label, :passkey_credential)
93
208
  end
94
209
 
210
+ # @!visibility public
211
+ # Verifies that the `sign_up_params` has an `:email` and `:passkey_label`.
212
+ #
213
+ # If either is missing or blank, a `400 Bad Request` JSON response is rendered.
214
+ #
215
+ # @example
216
+ # {"error": "Please enter your email address."}
95
217
  def require_email_and_passkey_label
96
218
  if sign_up_params[:email].blank?
97
219
  render json: { message: find_message(:email_missing) }, status: :bad_request
@@ -106,6 +228,18 @@ module Devise
106
228
  true
107
229
  end
108
230
 
231
+ # @!visibility public
232
+ # Verifies the registration challenge is correct.
233
+ #
234
+ # If the challenge failed, a `400 Bad Request` JSON
235
+ # response is rendered.
236
+ #
237
+ # @example
238
+ # {"error": "Please try a different passkey."}
239
+ #
240
+ # @see Warden::WebAuthn::RegistrationHelpers#verify_registration
241
+ # @see https://github.com/cedarcode/webauthn-ruby#verification-phase
242
+ # @see Warden::WebAuthn::ErrorKeyFinder#webauthn_error_key
109
243
  def verify_passkey_registration_challenge
110
244
  @webauthn_credential = verify_registration(relying_party: relying_party)
111
245
  rescue ::WebAuthn::Error => e
@@ -113,12 +247,17 @@ module Devise
113
247
  render json: { message: find_message(error_key) }, status: :bad_request
114
248
  end
115
249
 
116
- # If you have extra params to permit, append them to the sanitizer.
250
+ # @!visibility public
251
+ # Adds the generated WebAuthn User ID to `devise_parameter_sanitizer`'s permitted keys
117
252
  def configure_sign_up_params
118
- params[:user][:webauthn_id] = registration_user_id
253
+ params[resource_name][:webauthn_id] = registration_user_id
119
254
  devise_parameter_sanitizer.permit(:sign_up, keys: [:webauthn_id])
120
255
  end
121
256
 
257
+ # @!visibility public
258
+ # Prepares the user details for a WebAuthn registration request
259
+ # @see new_challenge
260
+ # @see https://github.com/cedarcode/webauthn-ruby#initiation-phase
122
261
  def user_details_for_registration
123
262
  store_registration_user_id
124
263
  { id: registration_user_id, name: sign_up_params[:email] }
@@ -8,7 +8,7 @@ module Devise
8
8
 
9
9
  included do
10
10
  include Warden::WebAuthn::AuthenticationInitiationHelpers
11
- include Warden::WebAuthn::StrategyHelpers
11
+ include Warden::WebAuthn::RackHelpers
12
12
 
13
13
  # Prepending is crucial to ensure that the relying party is set in the
14
14
  # request.env before the strategy is executed
@@ -29,8 +29,8 @@ module Devise
29
29
 
30
30
  protected
31
31
 
32
- def set_relying_party_in_request_env
33
- raise "need to define relying_party for this SessionsController"
32
+ def relying_party
33
+ raise NoMethodError, "need to define relying_party for this #{self.class.name}"
34
34
  end
35
35
  end
36
36
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "controllers/concerns/passkey_reauthentication"
3
+ require_relative "controllers/concerns/reauthentication"
4
4
  require_relative "controllers/concerns/reauthentication_challenge"
5
5
  require_relative "controllers/sessions_controller_concern"
6
6
  require_relative "controllers/registrations_controller_concern"
@@ -9,6 +9,60 @@ require_relative "controllers/passkeys_controller_concern"
9
9
 
10
10
  module Devise
11
11
  module Passkeys
12
+ # This module contains all the controller-level logic for:
13
+ #
14
+ # - User (resource) registration management (signup/delete account) using passkeys
15
+ # - User (resource) management of their passkeys
16
+ # - User (resource) authentication & reauthenticating using their passkeys
17
+ #
18
+ # Rather than having base classes, `Devise::Passkeys::Controllers` has a series of concerns
19
+ # that can be mixed into your app's controllers. This allows you to change behavior,
20
+ # and does not keep you stuck down a path that could be incompatible with your
21
+ # existing authentication setup.
22
+ #
23
+ # @example
24
+ # class Users::RegistrationsController < Devise::RegistrationsController
25
+ # include Devise::Passkeys::Controllers::RegistrationsControllerConcern
26
+ # end
27
+ #
28
+ #
29
+ # class Users::SessionsController < Devise::SessionsController
30
+ # include Devise::Passkeys::Controllers::SessionsControllerConcern
31
+ # # ... any custom code you need
32
+ #
33
+ # def relying_party
34
+ # WebAuthn::RelyingParty.new(...)
35
+ # end
36
+ # end
37
+ #
38
+ # # frozen_string_literal: true
39
+ #
40
+ # class Users::ReauthenticationController < DeviseController
41
+ # include Devise::Passkeys::Controllers::ReauthenticationControllerConcern
42
+ # # ... any custom code you need
43
+ #
44
+ # def relying_party
45
+ # WebAuthn::RelyingParty.new(...)
46
+ # end
47
+ # end
48
+ #
49
+ # # frozen_string_literal: true
50
+ #
51
+ # class Users::PasskeysController < DeviseController
52
+ # include Devise::Passkeys::Controllers::PasskeysControllerConcern
53
+ # # ... any custom code you need
54
+ #
55
+ # def relying_party
56
+ # WebAuthn::RelyingParty.new(...)
57
+ # end
58
+ # end
59
+ #
60
+ # *Note:* The `Devise::Passkeys::Controllers::Concerns` namespace is for:
61
+ # > Code, related to the concerns for controllers, that can be extracted into a standalone
62
+ # > module that can be included & extended as needed for apps that need
63
+ # > to do something custom with their setup.
64
+ # >
65
+ # > https://github.com/ruby-passkeys/devise-passkeys/issues/4#issuecomment-1590357907
12
66
  module Controllers
13
67
  end
14
68
  end
@@ -2,8 +2,16 @@
2
2
 
3
3
  module Devise
4
4
  module Models
5
+ # This is the actual module that gets included in your
6
+ # model when you include `:passkey_authenticatable` in the
7
+ # `devise` call (eg: `devise :passkey_authenticatable, ...`).
5
8
  module PasskeyAuthenticatable
6
- def after_passkey_authentication; end
9
+ # This is a callback that is called right after a successful passkey authentication.
10
+ #
11
+ # By default, it is a no-op, but you can override it in your model for any custom behavior
12
+ # (such as notifying the user of a new login).
13
+ # @param passkey [String] the passkey that was used for authentication
14
+ def after_passkey_authentication(passkey:); end
7
15
  end
8
16
  end
9
17
  end
@@ -35,8 +35,6 @@ module Devise
35
35
 
36
36
  private
37
37
 
38
- attr_accessor :maximum_passkeys_per_user
39
-
40
38
  def passkey_class(resource)
41
39
  if resource.respond_to?(:association) # ActiveRecord
42
40
  resource.association(:passkeys).klass
@@ -9,6 +9,13 @@ module Devise
9
9
  def authentication_challenge_key
10
10
  "#{mapping.singular}_current_reauthentication_challenge"
11
11
  end
12
+
13
+ # Reauthentication runs through Authentication (user_set)
14
+ # as part of its cycle, which would normally reset CSRF
15
+ # data in the session
16
+ def clean_up_csrf?
17
+ false
18
+ end
12
19
  end
13
20
  end
14
21
  end
@@ -32,7 +32,7 @@ module Devise
32
32
 
33
33
  if validate(resource)
34
34
  remember_me(resource)
35
- resource.after_passkey_authentication
35
+ resource.after_passkey_authentication(passkey: passkey)
36
36
  record_passkey_use(passkey: passkey)
37
37
  success!(resource)
38
38
  return
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Devise
4
4
  module Passkeys
5
- VERSION = "0.1.0"
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  end
@@ -11,7 +11,29 @@ require_relative "passkeys/reauthentication_strategy"
11
11
  require_relative "passkeys/version"
12
12
 
13
13
  module Devise
14
+ # This module provides a devise extension to use passkeys instead
15
+ # of passwords for user authentication.
16
+ #
17
+ # It is lightweight and non-configurable. It does what it has to do and
18
+ # leaves some manual implementation to you.
19
+ #
20
+ # Please consult the {file:README.md#label-Usage} for installation & configuration instructions;
21
+ # and the links below for additional reading about:
22
+ #
23
+ # - What passkeys are
24
+ # - The underlying gems used to build this devise extension
25
+ # - Platform support & user interface implementation guides
26
+ #
27
+ # @see https://webauthn.guide
28
+ # @see https://passkeys.dev
29
+ # @see https://fidoalliance.org/passkeys
30
+ # @see https://github.com/cedarcode/webauthn-ruby
31
+ # @see https://github.com/ruby-passkeys/warden-webauthn
14
32
  module Passkeys
33
+ # This is a helper method that creates and returns a passkey for
34
+ # the given user (`resource`), using the provided label & `WebAuthn::Credential`
35
+ # @see PasskeyIssuer#create_and_return_passkey
36
+ # @return A saved passkey for the the given user (`resource`)
15
37
  def self.create_and_return_passkey(resource:, label:, webauthn_credential:, extra_attributes: {})
16
38
  PasskeyIssuer.build.create_and_return_passkey(
17
39
  resource: resource,
@@ -22,8 +44,3 @@ module Devise
22
44
  end
23
45
  end
24
46
  end
25
-
26
- Devise.add_module :passkey_authenticatable,
27
- model: "devise/passkeys/model",
28
- strategy: true,
29
- no_input: true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise-passkeys
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Cannon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-07 00:00:00.000000000 Z
11
+ date: 2023-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: devise
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 4.7.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 4.7.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: warden-webauthn
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.2.0
33
+ version: 0.3.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 0.2.0
40
+ version: 0.3.0
41
41
  description: A Devise extension to use passkeys instead of passwords for authentication,
42
42
  using warden-webauthn
43
43
  email:
@@ -47,21 +47,24 @@ extensions: []
47
47
  extra_rdoc_files: []
48
48
  files:
49
49
  - ".rubocop.yml"
50
+ - ".yardopts"
50
51
  - Appraisals
51
52
  - CHANGELOG.md
52
53
  - CODE_OF_CONDUCT.md
54
+ - CONTRIBUTING.md
53
55
  - Gemfile
54
56
  - Gemfile.lock
55
57
  - LICENSE.txt
56
58
  - README.md
57
59
  - Rakefile
60
+ - THANKS.md
58
61
  - devise-passkeys.gemspec
59
62
  - gemfiles/.bundle/config
60
63
  - gemfiles/rails_6.gemfile
61
64
  - gemfiles/rails_7.gemfile
62
65
  - lib/devise/passkeys.rb
63
66
  - lib/devise/passkeys/controllers.rb
64
- - lib/devise/passkeys/controllers/concerns/passkey_reauthentication.rb
67
+ - lib/devise/passkeys/controllers/concerns/reauthentication.rb
65
68
  - lib/devise/passkeys/controllers/concerns/reauthentication_challenge.rb
66
69
  - lib/devise/passkeys/controllers/passkeys_controller_concern.rb
67
70
  - lib/devise/passkeys/controllers/reauthentication_controller_concern.rb