passkeys-rails 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +4 -4
  4. data/app/controllers/concerns/passkeys_rails/authentication.rb +29 -0
  5. data/app/controllers/passkeys_rails/application_controller.rb +22 -0
  6. data/app/controllers/passkeys_rails/passkeys_controller.rb +61 -0
  7. data/app/interactors/passkeys_rails/begin_authentication.rb +9 -0
  8. data/app/interactors/passkeys_rails/begin_challenge.rb +35 -0
  9. data/app/interactors/passkeys_rails/begin_registration.rb +23 -0
  10. data/app/interactors/passkeys_rails/finish_authentication.rb +53 -0
  11. data/app/interactors/passkeys_rails/finish_registration.rb +77 -0
  12. data/app/interactors/passkeys_rails/generate_auth_token.rb +27 -0
  13. data/app/interactors/passkeys_rails/refresh_token.rb +17 -0
  14. data/app/interactors/passkeys_rails/validate_auth_token.rb +33 -0
  15. data/app/models/concerns/passkeys_rails/authenticatable.rb +17 -0
  16. data/app/models/passkeys_rails/agent.rb +15 -0
  17. data/app/models/passkeys_rails/application_record.rb +5 -0
  18. data/app/models/passkeys_rails/error.rb +14 -0
  19. data/app/models/passkeys_rails/passkey.rb +8 -0
  20. data/config/initializers/application_controller.rb +12 -0
  21. data/config/routes.rb +1 -1
  22. data/lib/generators/passkeys_rails/USAGE +1 -1
  23. data/lib/generators/passkeys_rails/install_generator.rb +12 -14
  24. data/lib/generators/passkeys_rails/templates/README +1 -1
  25. data/lib/generators/passkeys_rails/templates/passkeys_rails_config.rb +1 -1
  26. data/lib/passkeys-rails.rb +21 -23
  27. data/lib/passkeys_rails/engine.rb +21 -0
  28. data/lib/passkeys_rails/railtie.rb +17 -0
  29. data/lib/passkeys_rails/version.rb +3 -0
  30. metadata +22 -24
  31. data/app/assets/config/passkeys_rails_manifest.js +0 -1
  32. data/app/assets/stylesheets/passkeys_rails/application.css +0 -15
  33. data/app/controllers/passkeys/rails/application_controller.rb +0 -24
  34. data/app/controllers/passkeys/rails/passkeys_controller.rb +0 -63
  35. data/app/models/concerns/passkeys/rails/authenticatable.rb +0 -19
  36. data/app/models/passkeys/rails/agent.rb +0 -17
  37. data/app/models/passkeys/rails/application_record.rb +0 -7
  38. data/app/models/passkeys/rails/error.rb +0 -16
  39. data/app/models/passkeys/rails/passkey.rb +0 -10
  40. data/app/views/layouts/passkeys/rails/application.html.erb +0 -15
  41. data/lib/passkeys/rails/controllers/helpers.rb +0 -33
  42. data/lib/passkeys/rails/engine.rb +0 -44
  43. data/lib/passkeys/rails/interactors/begin_authentication.rb +0 -11
  44. data/lib/passkeys/rails/interactors/begin_challenge.rb +0 -37
  45. data/lib/passkeys/rails/interactors/begin_registration.rb +0 -25
  46. data/lib/passkeys/rails/interactors/finish_authentication.rb +0 -55
  47. data/lib/passkeys/rails/interactors/finish_registration.rb +0 -79
  48. data/lib/passkeys/rails/interactors/generate_auth_token.rb +0 -29
  49. data/lib/passkeys/rails/interactors/refresh_token.rb +0 -19
  50. data/lib/passkeys/rails/interactors/validate_auth_token.rb +0 -35
  51. data/lib/passkeys/rails/railtie.rb +0 -19
  52. data/lib/passkeys/rails/version.rb +0 -5
@@ -0,0 +1,21 @@
1
+ require "rails"
2
+ require "active_support/core_ext/numeric/time"
3
+ require "active_support/dependencies"
4
+
5
+ require "interactor"
6
+ require "jwt"
7
+ require "webauthn"
8
+
9
+ module PasskeysRails
10
+ class Engine < ::Rails::Engine
11
+ isolate_namespace PasskeysRails
12
+
13
+ config.generators do |g|
14
+ g.test_framework :rspec
15
+ g.fixture_replacement :factory_bot
16
+ g.factory_bot dir: 'spec/factories'
17
+ g.assets false
18
+ g.helper false
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ require 'passkeys-rails'
2
+ require 'rails'
3
+
4
+ module PasskeysRails
5
+ class Railtie < ::Rails::Railtie
6
+ railtie_name :passkeys_rails
7
+
8
+ rake_tasks do
9
+ path = File.expand_path(__dir__)
10
+ Dir.glob("#{path}/tasks/**/*.rake").each { |f| load f }
11
+ end
12
+
13
+ generators do
14
+ require "generators/passkeys_rails/install_generator"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module PasskeysRails
2
+ VERSION = "0.1.4".freeze
3
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passkeys-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Troy Anderson
@@ -351,16 +351,23 @@ files:
351
351
  - MIT-LICENSE
352
352
  - README.md
353
353
  - Rakefile
354
- - app/assets/config/passkeys_rails_manifest.js
355
- - app/assets/stylesheets/passkeys_rails/application.css
356
- - app/controllers/passkeys/rails/application_controller.rb
357
- - app/controllers/passkeys/rails/passkeys_controller.rb
358
- - app/models/concerns/passkeys/rails/authenticatable.rb
359
- - app/models/passkeys/rails/agent.rb
360
- - app/models/passkeys/rails/application_record.rb
361
- - app/models/passkeys/rails/error.rb
362
- - app/models/passkeys/rails/passkey.rb
363
- - app/views/layouts/passkeys/rails/application.html.erb
354
+ - app/controllers/concerns/passkeys_rails/authentication.rb
355
+ - app/controllers/passkeys_rails/application_controller.rb
356
+ - app/controllers/passkeys_rails/passkeys_controller.rb
357
+ - app/interactors/passkeys_rails/begin_authentication.rb
358
+ - app/interactors/passkeys_rails/begin_challenge.rb
359
+ - app/interactors/passkeys_rails/begin_registration.rb
360
+ - app/interactors/passkeys_rails/finish_authentication.rb
361
+ - app/interactors/passkeys_rails/finish_registration.rb
362
+ - app/interactors/passkeys_rails/generate_auth_token.rb
363
+ - app/interactors/passkeys_rails/refresh_token.rb
364
+ - app/interactors/passkeys_rails/validate_auth_token.rb
365
+ - app/models/concerns/passkeys_rails/authenticatable.rb
366
+ - app/models/passkeys_rails/agent.rb
367
+ - app/models/passkeys_rails/application_record.rb
368
+ - app/models/passkeys_rails/error.rb
369
+ - app/models/passkeys_rails/passkey.rb
370
+ - config/initializers/application_controller.rb
364
371
  - config/routes.rb
365
372
  - db/migrate/20230620012530_create_passkeys_rails_agents.rb
366
373
  - db/migrate/20230620012600_create_passkeys_rails_passkeys.rb
@@ -369,18 +376,9 @@ files:
369
376
  - lib/generators/passkeys_rails/templates/README
370
377
  - lib/generators/passkeys_rails/templates/passkeys_rails_config.rb
371
378
  - lib/passkeys-rails.rb
372
- - lib/passkeys/rails/controllers/helpers.rb
373
- - lib/passkeys/rails/engine.rb
374
- - lib/passkeys/rails/interactors/begin_authentication.rb
375
- - lib/passkeys/rails/interactors/begin_challenge.rb
376
- - lib/passkeys/rails/interactors/begin_registration.rb
377
- - lib/passkeys/rails/interactors/finish_authentication.rb
378
- - lib/passkeys/rails/interactors/finish_registration.rb
379
- - lib/passkeys/rails/interactors/generate_auth_token.rb
380
- - lib/passkeys/rails/interactors/refresh_token.rb
381
- - lib/passkeys/rails/interactors/validate_auth_token.rb
382
- - lib/passkeys/rails/railtie.rb
383
- - lib/passkeys/rails/version.rb
379
+ - lib/passkeys_rails/engine.rb
380
+ - lib/passkeys_rails/railtie.rb
381
+ - lib/passkeys_rails/version.rb
384
382
  - lib/tasks/passkeys_rails_tasks.rake
385
383
  homepage: https://github.com/alliedcode/passkeys-rails
386
384
  licenses:
@@ -405,7 +403,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
405
403
  - !ruby/object:Gem::Version
406
404
  version: '0'
407
405
  requirements: []
408
- rubygems_version: 3.4.12
406
+ rubygems_version: 3.4.17
409
407
  signing_key:
410
408
  specification_version: 4
411
409
  summary: PassKey authentication back end with simple API
@@ -1 +0,0 @@
1
- //= link_directory ../stylesheets/passkeys_rails .css
@@ -1,15 +0,0 @@
1
- /*
2
- * This is a manifest file that'll be compiled into application.css, which will include all the files
3
- * listed below.
4
- *
5
- * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
- * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
- *
8
- * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
- * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
- * files in this directory. Styles in this file should be added after the last require_* statement.
11
- * It is generally better to create a new file per style scope.
12
- *
13
- *= require_tree .
14
- *= require_self
15
- */
@@ -1,24 +0,0 @@
1
- module Passkeys
2
- module Rails
3
- class ApplicationController < ActionController::Base
4
- rescue_from ::Interactor::Failure, with: :handle_interactor_failure
5
- rescue_from ActionController::ParameterMissing, with: :handle_missing_parameter
6
-
7
- protected
8
-
9
- def handle_missing_parameter(error)
10
- render_error(:authentication, 'missing_parameter', error.message)
11
- end
12
-
13
- def handle_interactor_failure(failure)
14
- render_error(:authentication, failure.context.code, failure.context.message)
15
- end
16
-
17
- private
18
-
19
- def render_error(context, code, message, status: :unprocessable_entity)
20
- render json: { error: { context:, code:, message: } }, status:
21
- end
22
- end
23
- end
24
- end
@@ -1,63 +0,0 @@
1
- module Passkeys
2
- module Rails
3
- class PasskeysController < ApplicationController
4
- def challenge
5
- result = Passkeys::Rails::BeginChallenge.call!(username: challenge_params[:username])
6
-
7
- # Store the challenge so we can verify the future register or authentication request
8
- session[:passkeys_rails] = result.session_data
9
-
10
- render json: result.response.as_json
11
- end
12
-
13
- def register
14
- result = Passkeys::Rails::FinishRegistration.call!(credential: attestation_credential_params.to_h,
15
- authenticatable_class:,
16
- username: session.dig(:passkeys_rails, :username),
17
- challenge: session.dig(:passkeys_rails, :challenge))
18
-
19
- render json: { username: result.username, auth_token: result.auth_token }
20
- end
21
-
22
- def authenticate
23
- result = Passkeys::Rails::FinishAuthentication.call!(credential: authentication_params.to_h,
24
- challenge: session.dig(:passkeys_rails, :challenge))
25
-
26
- render json: { username: result.username, auth_token: result.auth_token }
27
- end
28
-
29
- def refresh
30
- result = Passkeys::Rails::RefreshToken.call!(token: refresh_params[:auth_token])
31
- render json: { username: result.username, auth_token: result.auth_token }
32
- end
33
-
34
- protected
35
-
36
- def challenge_params
37
- params.permit(:username)
38
- end
39
-
40
- def attestation_credential_params
41
- credential = params.require(:credential)
42
- credential.require(%i[id rawId type response])
43
- credential.require(:response).require(%i[attestationObject clientDataJSON])
44
- credential.permit(:id, :rawId, :type, { response: %i[attestationObject clientDataJSON] })
45
- end
46
-
47
- def authenticatable_class
48
- params[:authenticatable_class]
49
- end
50
-
51
- def authentication_params
52
- params.require(%i[id rawId type response])
53
- params.require(:response).require(%i[authenticatorData clientDataJSON signature userHandle])
54
- params.permit(:id, :rawId, :type, { response: %i[authenticatorData clientDataJSON signature userHandle] })
55
- end
56
-
57
- def refresh_params
58
- params.require(:auth_token)
59
- params.permit(:auth_token)
60
- end
61
- end
62
- end
63
- end
@@ -1,19 +0,0 @@
1
- require 'active_support/concern'
2
-
3
- module Passkeys
4
- module Rails
5
- module Authenticatable
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- has_one :agent, as: :authenticatable
10
-
11
- delegate :registered?, to: :agent, allow_nil: true
12
-
13
- def registering_with(_agent)
14
- # initialize required attributes
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,17 +0,0 @@
1
- module Passkeys
2
- module Rails
3
- class Agent < ApplicationRecord
4
- belongs_to :authenticatable, polymorphic: true, optional: true
5
- has_many :passkeys
6
-
7
- scope :registered, -> { where.not registered_at: nil }
8
- scope :unregistered, -> { where registered_at: nil }
9
-
10
- validates :username, presence: true, uniqueness: true
11
-
12
- def registered?
13
- registered_at.present?
14
- end
15
- end
16
- end
17
- end
@@ -1,7 +0,0 @@
1
- module Passkeys
2
- module Rails
3
- class ApplicationRecord < ActiveRecord::Base
4
- self.abstract_class = true
5
- end
6
- end
7
- end
@@ -1,16 +0,0 @@
1
- module Passkeys
2
- module Rails
3
- class Error < StandardError
4
- attr_reader :hash
5
-
6
- def initialize(message, hash = {})
7
- @hash = hash
8
- super(message)
9
- end
10
-
11
- def to_h
12
- { error: hash.merge(context: message) }
13
- end
14
- end
15
- end
16
- end
@@ -1,10 +0,0 @@
1
- module Passkeys
2
- module Rails
3
- class Passkey < ApplicationRecord
4
- belongs_to :agent
5
- validates :identifier, presence: true, uniqueness: true
6
- validates :public_key, presence: true
7
- validates :sign_count, presence: true
8
- end
9
- end
10
- end
@@ -1,15 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>Mobile pass</title>
5
- <%= csrf_meta_tags %>
6
- <%= csp_meta_tag %>
7
-
8
- <%= stylesheet_link_tag "passkeys_rails/application", media: "all" %>
9
- </head>
10
- <body>
11
-
12
- <%= yield %>
13
-
14
- </body>
15
- </html>
@@ -1,33 +0,0 @@
1
- module Passkeys
2
- module Rails
3
- module Controllers
4
- module Helpers
5
- extend ActiveSupport::Concern
6
-
7
- included do
8
- rescue_from Passkeys::Rails::Error do |e|
9
- render json: e.to_h, status: :unauthorized
10
- end
11
- end
12
-
13
- def current_agent
14
- return nil if request.headers['HTTP_X_AUTH'].blank?
15
-
16
- @current_agent ||= validated_auth_token&.success? && validated_auth_token&.agent
17
- end
18
-
19
- def authenticate_passkey!
20
- return if validated_auth_token.success?
21
-
22
- raise Passkeys::Rails::Error.new(:authentication,
23
- code: :unauthorized,
24
- message: "You are not authorized to access this resource.")
25
- end
26
-
27
- def validated_auth_token
28
- @validated_auth_token ||= Passkeys::Rails::ValidateAuthToken.call(auth_token: request.headers['HTTP_X_AUTH'])
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,44 +0,0 @@
1
- require "rails"
2
- require "active_support/core_ext/numeric/time"
3
- require "active_support/dependencies"
4
-
5
- require "interactor"
6
- require "jwt"
7
- require "webauthn"
8
-
9
- require_relative 'controllers/helpers'
10
- require_relative "interactors/begin_authentication"
11
- require_relative "interactors/begin_challenge"
12
- require_relative "interactors/begin_registration"
13
- require_relative "interactors/finish_authentication"
14
- require_relative "interactors/finish_registration"
15
- require_relative "interactors/generate_auth_token"
16
- require_relative "interactors/refresh_token"
17
- require_relative "interactors/validate_auth_token"
18
-
19
- module Passkeys
20
- module Rails
21
- class Engine < ::Rails::Engine
22
- isolate_namespace Passkeys::Rails
23
-
24
- config.generators do |g|
25
- g.test_framework :rspec
26
- g.fixture_replacement :factory_bot
27
- g.factory_bot dir: 'spec/factories'
28
- g.assets false
29
- g.helper false
30
- end
31
-
32
- # Include helpers
33
- initializer "passkeys-rails.helpers" do
34
- ActiveSupport.on_load(:action_controller_base) do
35
- include Passkeys::Rails::Controllers::Helpers
36
- end
37
-
38
- ActiveSupport.on_load(:action_controller_api) do
39
- include Passkeys::Rails::Controllers::Helpers
40
- end
41
- end
42
- end
43
- end
44
- end
@@ -1,11 +0,0 @@
1
- module Passkeys
2
- module Rails
3
- class BeginAuthentication
4
- include Interactor
5
-
6
- def call
7
- context.options = WebAuthn::Credential.options_for_get
8
- end
9
- end
10
- end
11
- end
@@ -1,37 +0,0 @@
1
- module Passkeys
2
- module Rails
3
- class BeginChallenge
4
- include Interactor
5
-
6
- delegate :username, to: :context
7
-
8
- def call
9
- result = generate_challenge!
10
-
11
- options = result.options
12
-
13
- context.response = options
14
- context.session_data = session_data(options)
15
- rescue Interactor::Failure => e
16
- context.fail! code: e.context.code, message: e.context.message
17
- end
18
-
19
- private
20
-
21
- def generate_challenge!
22
- if username.present?
23
- BeginRegistration.call!(username:)
24
- else
25
- BeginAuthentication.call!
26
- end
27
- end
28
-
29
- def session_data(options)
30
- {
31
- username:,
32
- challenge: WebAuthn.standard_encoder.encode(options.challenge)
33
- }
34
- end
35
- end
36
- end
37
- end
@@ -1,25 +0,0 @@
1
- module Passkeys
2
- module Rails
3
- class BeginRegistration
4
- include Interactor
5
-
6
- delegate :username, to: :context
7
-
8
- def call
9
- agent = create_unregistered_agent
10
-
11
- context.options = WebAuthn::Credential.options_for_create(user: { id: agent.webauthn_identifier, name: agent.username })
12
- end
13
-
14
- private
15
-
16
- def create_unregistered_agent
17
- agent = Agent.create(username:, webauthn_identifier: WebAuthn.generate_user_id)
18
-
19
- context.fail!(code: :validation_errors, message: agent.errors.full_messages.to_sentence) unless agent.valid?
20
-
21
- agent
22
- end
23
- end
24
- end
25
- end
@@ -1,55 +0,0 @@
1
- # Finish authentication ceremony
2
- module Passkeys
3
- module Rails
4
- class FinishAuthentication
5
- include Interactor
6
-
7
- delegate :credential, :challenge, to: :context
8
-
9
- def call
10
- verify_credential!
11
-
12
- context.username = agent.username
13
- context.auth_token = GenerateAuthToken.call!(agent:).auth_token
14
- rescue Interactor::Failure => e
15
- context.fail! code: e.context.code, message: e.context.message
16
- end
17
-
18
- private
19
-
20
- def verify_credential!
21
- webauthn_credential.verify(
22
- challenge,
23
- public_key: passkey.public_key,
24
- sign_count: passkey.sign_count
25
- )
26
-
27
- passkey.update!(sign_count: webauthn_credential.sign_count)
28
- agent.update!(last_authenticated_at: Time.current)
29
- rescue WebAuthn::SignCountVerificationError
30
- # Cryptographic verification of the authenticator data succeeded, but the signature counter was less than or equal
31
- # to the stored value. This can have several reasons and depending on your risk tolerance you can choose to fail or
32
- # pass authentication. For more information see https://www.w3.org/TR/webauthn/#sign-counter
33
- rescue WebAuthn::Error => e
34
- context.fail!(code: :webauthn_error, message: e.message)
35
- end
36
-
37
- def webauthn_credential
38
- @webauthn_credential ||= WebAuthn::Credential.from_get(credential)
39
- end
40
-
41
- def passkey
42
- @passkey ||= begin
43
- passkey = Passkey.find_by(identifier: webauthn_credential.id)
44
- context.fail!(code: :passkey_not_found, message: "Unable to find the specified passkey") if passkey.blank?
45
-
46
- passkey
47
- end
48
- end
49
-
50
- def agent
51
- passkey.agent
52
- end
53
- end
54
- end
55
- end
@@ -1,79 +0,0 @@
1
- # Finish registration ceremony
2
- module Passkeys
3
- module Rails
4
- class FinishRegistration
5
- include Interactor
6
-
7
- delegate :credential, :username, :challenge, :authenticatable_class, to: :context
8
-
9
- def call
10
- verify_credential!
11
- store_passkey_and_register_agent!
12
-
13
- context.username = agent.username
14
- context.auth_token = GenerateAuthToken.call!(agent:).auth_token
15
- rescue Interactor::Failure => e
16
- context.fail! code: e.context.code, message: e.context.message
17
- end
18
-
19
- private
20
-
21
- def verify_credential!
22
- webauthn_credential.verify(challenge)
23
- rescue WebAuthn::Error => e
24
- context.fail!(code: :webauthn_error, message: e.message)
25
- rescue StandardError => e
26
- context.fail!(code: :error, message: e.message)
27
- end
28
-
29
- def store_passkey_and_register_agent!
30
- agent.transaction do
31
- begin
32
- # Store Credential ID, Credential Public Key and Sign Count for future authentications
33
- agent.passkeys.create!(
34
- identifier: webauthn_credential.id,
35
- public_key: webauthn_credential.public_key,
36
- sign_count: webauthn_credential.sign_count
37
- )
38
-
39
- agent.update! registered_at: Time.current
40
- rescue StandardError => e
41
- context.fail! code: :passkey_error, message: e.message
42
- end
43
-
44
- create_authenticatable! if authenticatable_class.present?
45
- end
46
- end
47
-
48
- def create_authenticatable!
49
- klass = begin
50
- authenticatable_class.constantize
51
- rescue StandardError
52
- context.fail!(code: :invalid_authenticatable_class, message: "authenticatable_class (#{authenticatable_class}) is not defined")
53
- end
54
-
55
- begin
56
- authenticatable = klass.create! do |obj|
57
- obj.registering_with(agent) if obj.respond_to?(:registering_with)
58
- end
59
- agent.update!(authenticatable:)
60
- rescue ActiveRecord::RecordInvalid => e
61
- context.fail!(code: :record_invalid, message: e.message)
62
- end
63
- end
64
-
65
- def webauthn_credential
66
- @webauthn_credential ||= WebAuthn::Credential.from_create(credential)
67
- end
68
-
69
- def agent
70
- @agent ||= begin
71
- agent = Agent.find_by(username:)
72
- context.fail!(code: :agent_not_found, message: "Agent not found for session value: \"#{username}\"") if agent.blank?
73
-
74
- agent
75
- end
76
- end
77
- end
78
- end
79
- end
@@ -1,29 +0,0 @@
1
- module Passkeys
2
- module Rails
3
- class GenerateAuthToken
4
- include Interactor
5
-
6
- delegate :agent, to: :context
7
-
8
- def call
9
- context.auth_token = generate_auth_token
10
- end
11
-
12
- private
13
-
14
- def generate_auth_token
15
- JWT.encode(jwt_payload,
16
- Passkeys::Rails.auth_token_secret,
17
- Passkeys::Rails.auth_token_algorithm)
18
- end
19
-
20
- def jwt_payload
21
- expiration = (Time.current + Passkeys::Rails.auth_token_expires_in).to_i
22
-
23
- payload = { agent_id: agent.id }
24
- payload[:exp] = expiration unless expiration.zero?
25
- payload
26
- end
27
- end
28
- end
29
- end
@@ -1,19 +0,0 @@
1
- # Finish authentication ceremony
2
- module Passkeys
3
- module Rails
4
- class RefreshToken
5
- include Interactor
6
-
7
- delegate :token, to: :context
8
-
9
- def call
10
- agent = ValidateAuthToken.call!(auth_token: token).agent
11
-
12
- context.username = agent.username
13
- context.auth_token = GenerateAuthToken.call!(agent:).auth_token
14
- rescue Interactor::Failure => e
15
- context.fail! code: e.context.code, message: e.context.message
16
- end
17
- end
18
- end
19
- end