Skip to content

Commit

Permalink
Refresh Credentials Hook (#79)
Browse files Browse the repository at this point in the history
* - Utilize hook (Refreshable) for setting initial credentials_refreshed_at value;
- Switch to warden session scope for simplicity;
- Move requiring of "hooks/refreshable" to main devise-otp.rb file;

* - Use warden.session for refresh_return_url too
- Remove "scoped" verbiage from session properties (since scope is now applied via warden);
- Remove comment regarding cookie scope for otp_refresh_property (now applied via warden);

* add CHANGELOG entry;
  • Loading branch information
strouptl authored May 30, 2024
1 parent 62584a2 commit ef9d8a0
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 12 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

## UNRELEASED

Summary: Move refresh\_credentials functionality to dedicated hook (Refreshable);

Details:
- Add Refreshable hook, and tie into after\_set\_user calback;
- Utilize native warden session for scoping of credentials\_refreshed\_at and refresh\_return\_url properties;
- Remove otp\_refresh\_credentials from sessions hook (no longer needed);

## UNRELEASED

Summary: Move mandatory OTP functionality to the helper layer to ensure that it is enforced throughout application (rather than one time at log in).

Details:
Expand Down
2 changes: 2 additions & 0 deletions lib/devise-otp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ module Controllers

require "devise_otp_authenticatable/routes"
require "devise_otp_authenticatable/engine"
require "devise_otp_authenticatable/hooks/refreshable"

#
# update Devise module with additions needed for DeviseOtpAuthenticatable
Expand Down Expand Up @@ -82,6 +83,7 @@ module Otp
Devise.add_module :otp_authenticatable,
controller: :tokens,
model: "devise_otp_authenticatable/models/otp_authenticatable", route: :otp

#
# add PublicHelpers after adding Devise module to ensure that per-mapping routes from above are included
#
Expand Down
19 changes: 9 additions & 10 deletions lib/devise_otp_authenticatable/controllers/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,23 @@ def ensure_resource!
end
end

# fixme do cookies and persistence need to be scoped? probably
#
# check if the resource needs a credentials refresh. IE, they need to be asked a password again to access
# this resource.
#
def needs_credentials_refresh?(resource)
return false unless resource.class.otp_credentials_refresh

(!session[otp_scoped_refresh_property].present? ||
(session[otp_scoped_refresh_property] < DateTime.now)).tap { |need| otp_set_refresh_return_url if need }
(!warden.session[otp_refresh_property].present? ||
(warden.session[otp_refresh_property] < DateTime.now)).tap { |need| otp_set_refresh_return_url if need }
end

#
# credentials are refreshed
#
def otp_refresh_credentials_for(resource)
return false unless resource.class.otp_credentials_refresh
session[otp_scoped_refresh_property] = (Time.now + resource.class.otp_credentials_refresh)
warden.session[otp_refresh_property] = (Time.now + resource.class.otp_credentials_refresh)
end

#
Expand Down Expand Up @@ -85,19 +84,19 @@ def otp_set_trusted_device_for(resource)
end

def otp_set_refresh_return_url
session[otp_scoped_refresh_return_url_property] = request.fullpath
warden.session[otp_refresh_return_url_property] = request.fullpath
end

def otp_fetch_refresh_return_url
session.delete(otp_scoped_refresh_return_url_property) { :root }
warden.session.delete(otp_refresh_return_url_property) { :root }
end

def otp_scoped_refresh_return_url_property
"otp_#{resource_name}refresh_return_url".to_sym
def otp_refresh_return_url_property
:refresh_return_url
end

def otp_scoped_refresh_property
"otp_#{resource_name}refresh_after".to_sym
def otp_refresh_property
:credentials_refreshed_at
end

def otp_scoped_persistence_cookie
Expand Down
5 changes: 5 additions & 0 deletions lib/devise_otp_authenticatable/hooks/refreshable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# After each sign in, update credentials refreshed at time
Warden::Manager.after_set_user except: :fetch do |record, warden, options|
warden.session[:credentials_refreshed_at] = (Time.now + record.class.otp_credentials_refresh)
end

2 changes: 0 additions & 2 deletions lib/devise_otp_authenticatable/hooks/sessions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ def create_with_otp
devise_stored_location = stored_location_for(resource) # Grab the current stored location before it gets lost by warden.logout
store_location_for(resource, devise_stored_location) # Restore it since #stored_location_for removes it

otp_refresh_credentials_for(resource)

yield resource if block_given?
if otp_challenge_required_on?(resource)
challenge = resource.generate_otp_challenge!
Expand Down

0 comments on commit ef9d8a0

Please sign in to comment.