SessionExpirable
All good things come to an end: At least that’s how it’s supposed to work.
SessionExpirable is an enhanced version of Devise[https://github.com/plataformatec/devise]‘s timeoutable
module that ensures that no session is allowed to last forever.
Like Devise timeoutable
, SessionExpirable adds a timestamp to sessions indicating the last time that the session was used, and checks these timestamps when a session is used to sign a user in. A configurable timeout_in
option controls how long inactive sessions are considered valid.
Differences with Devise Timeoutable
When timeoutable
reads a session that does not contain a timestamp, timestamp validation is bypassed: A session without a timestamp will never be considered as having timed out.
In order to prevent the abuse of non-expiring sessions, SessionExpirable treats sessions without timestamps as having already expired.
Another difference is that in the case of a timeout, timeoutable
prevents other authentication strategies from being tried, although it has custom logic to allow Devise rememberable
to work in spite of a timed-out session.
SessionExpirable does not allow a timed-out session to interfere with any authentication strategies that are configured. One consequence is that SessionExpirable does not support invalidation of authentication tokens from the Devise token_authenticatable
module when a request with a valid authentication token is accompanied by an expired session.
One final difference is that SessionExpirable does not invoke the Devise FailureApp for requests that do not require authentication.
Configuration
Add devise_session_expirable
to your Gemfile:
gem 'devise_session_expirable'
Include :session_expirable
in your devise user model declaration:
class User < ActiveRecord::Base
devise :database_authenticatable, :session_expirable # ...
end
Then update the Devise initializer:
Devise.setup do |config|
# ...
config.timeout_in = 15.minutes
config.default_last_request_at = Time.parse('2013-02-16T00:00:00Z')
# ...
end
Migrating from non-expiring sessions
The default_last_request_at
option is intended to enable a less disruptive migration if sessions without timestamps have already been issued. The configured value will be used in place of the timestamp for sessions which don’t have one.
If default_last_request_at
is configured, it should be set to a fixed date/time, ideally matching the time of deployment. If set to a dynamic time (e.g. Time.now), the lifetime of sessions without timestamps will be extended every time Rails is initialized.
After the timeout_in
interval passes, any legacy sessions will have expired and default_last_request_at
can be unset.
Alternatives
As long as you reset your secret_token when configuring Devise timeoutable
to your rails application and avoid authenticating for actions which set devise.skip_trackable
in the rack environment, you will have eliminated at least two possible sources of non-expiring sessions.
Acknowledgements
This module was adapted from Devise’s timeoutable
module.
Thanks to the creators and maintainers of Devise and Warden for a truly extensible authentication library.
Contributing to devise_session_expirable
-
Fork the project.
-
Start a feature/bugfix branch.
-
Commit and push.
-
Make sure to add tests.
Copyright
Copyright © 2013 Riley Lynch, Teleological Software, LLC. See LICENSE.txt for further details.