Code Monkey home page Code Monkey logo

auto-session-timeout's Introduction

Build Status

Auto::Session::Timeout

Provides automatic session timeout in a Rails application. Very easy to install and configure. Have you ever wanted to force your users off your app if they go idle for a certain period of time? Many online banking sites use this technique. If your app is used on any kind of public computer system, this gem is a necessity.

Installation

Add this line to your application's Gemfile:

gem 'auto-session-timeout'

And then execute:

$ bundle

Or install it yourself as:

$ gem install auto-session-timeout

Usage

After installing, tell your application controller to use auto timeout:

class ApplicationController < ActionController::Base
  auto_session_timeout 1.hour
end

This will use a global timeout of 1 hour. The gem assumes your authentication provider has a #current_user method that returns the currently logged in user.

If you want to specify a custom timeout value per user, don't pass a value to the controller as shown above. Instead, override #auto_timeout in your #current_user model. This is typically the User class:

class ApplicationController < ActionController::Base
  auto_session_timeout
end

class User < ActiveRecord::Base
  def auto_timeout
    15.minutes
  end
end

You will also need to insert a call to the #auto_session_timeout_js helper method inside the body tags in your views. The easiest way to do this is to insert it once inside your default or application-wide layout. Make sure you are only rendering if the user is logged in, otherwise the gem will attempt to force non-existent sessions to timeout, wreaking havoc:

<body>
  <% if current_user %>
    <%= auto_session_timeout_js %>
  <% end %>
</body>

You need to setup two actions: one to return the session status and another that runs when the session times out. You can use the default actions included with the gem by inserting this line in your target controller (most likely your user or session controller):

class SessionsController < ApplicationController
  auto_session_timeout_actions
end

To customize the default actions, simply override them. You can call the #render_session_status and #render_session_timeout methods to use the default implementation from the gem, or you can define the actions entirely with your own custom code:

class SessionsController < ApplicationController
  def active
    render_session_status
  end

  def timeout
    render_session_timeout
  end
end

In any of these cases, make sure to properly map the actions in your routes.rb file:

get "active",  to: "sessions#active"
get "timeout", to: "sessions#timeout"

You're done! Enjoy watching your sessions automatically timeout.

Using with Devise

When using Devise for authentication you will need to add a scoped sessions controller and call the timeout actions helper there. For example:

class Users::SessionsController < Devise::SessionsController
  auto_session_timeout_actions
end

In your routes.rb file you will need to declare your scoped controller and declare the timeout actions inside the same Devise scope:

Rails.application.routes.draw do
  devise_for :users, controllers: { sessions: "users/sessions" }
  
  devise_scope :user do
    get "active", to: "users/sessions#active"
    get "timeout", to: "users/sessions#timeout"
  end
end

You can use Devise's #user_signed_in? method when you call the JS helper method in your view:

<body>
  <% if user_signed_in? %>
    <%= auto_session_timeout_js %>
  <% end %>
</body>

Optional Configuration

By default, the JavaScript code checks the server every 60 seconds for active sessions. If you prefer that it check more frequently, pass a frequency attribute to the helper method. The frequency is given in seconds. The following example checks the server every 15 seconds:

<body>
  <% if current_user %>
    <%= auto_session_timeout_js frequency: 15 %>
  <% end %>
</body>

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Resources

auto-session-timeout's People

Contributors

amoose avatar cprodhomme avatar davegudge avatar emilos avatar gearoiddc avatar jasonheecs avatar jlcapps avatar junaiduk avatar krishnasrihari avatar mjbass avatar ozzlopz avatar pelargir avatar quainjn avatar tim-s-ccs avatar webaholik avatar zaimramlan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

auto-session-timeout's Issues

this gem is not compatible with turbolinks

When use turbolinks, consider clicking the 'next page' button of a list for several times, the trigger of post '/active' will repeat for this times. e.g. I auto_session_timeout_js frequency: 120, and then click 'next page' for 5 times, then every 120 seconds will post to /action for 5 times. That's caused by write the codes in body. The correct way to do is wrapping the codes in $('document').on('turbolinks:load', function(){}).

Improvement for project/Inspiration for others(?): Stimulus Controller

Hello and thank you very much for this gem.

This is not a bug - it is more kind of a documentation improvement or suggestion to create a Node.js package.

I am using Rails 7.1 with Hotwire Stimulus-Rails/Turbo-Rails and ended up writing my own Stimulus controller for AutoSessionTimeout, based on the provided JS.

I experimented a bit with Stimulus and came up with this solution.

My Stimulus controller provides:

  • Session Timeout check (as provided by the gem)
  • Keepalive (on 'keypress' and 'scroll@window' event) -> See ApplicationHelper
    • This may be of interest for #37
  • Page reload after session_timeout (Working fine with Devise and Turbo)

This is my first attempt to dig into JS - if there are any mistakes or possible improvements, please let me know :-)

Stimulus controllers customizations (thanks to #16):

app/javascript/controllers/index.js

[...]
import AutoSessionTimeoutController from "./auto_session_timeout_controller"
application.register("auto-session-timeout", AutoSessionTimeoutController)
[...]

app/javascript/controllers/auto_session_timeout_controller.js

import {Controller} from "@hotwired/stimulus"

// Connects to data-controller="auto-session-timeout"
export default class extends Controller {

    initialize() {
        this.intervalId = 0;
        this.waitUntil = 0

        this.frequency = Number(this.element.dataset.astFrequency) || 60;
        this.active_path = String(this.element.dataset.astActivePath)
        this.keep_alive_path = String(this.element.dataset.astKeepAlivePath)

        super.initialize();
    }

    connect() {
        if (this.active_path === 'undefined') {
            console.log('auto-session-timeout message:')
            console.log('ast-active-path is not defined - value: ' + this.active_path);
            return;
        }

        if (this.keep_alive_path === 'undefined') {
            console.log('auto-session-timeout message:')
            console.log('ast-ping-path is not defined - value: ' + this.keep_alive_path);
            return;
        }

        this.intervalId = setInterval(this.check_timeout.bind(this), (this.frequency * 1000));
    }

    disconnect() {
        clearInterval(this.intervalId);
    }

    check_return_value(event) {
        var status = event.target.status;
        var response = event.target.response;

        if (status === 200 && (response === false || response === 'false' || response === null)) {
            location.reload();
        }
    }

    check_timeout() {
        const request = new XMLHttpRequest();

        request.onload = this.check_return_value.bind(this);

        request.open('GET', this.active_path, true);
        request.responseType = 'json';
        request.send();
    }

    keep_alive() {
        const request = new XMLHttpRequest();

        if (Date.now() >= this.waitUntil) {
            this.waitUntil = Date.now() + 1000 * this.frequency;
        } else {
            return;
        }

        request.onload = this.check_return_value.bind(this);

        request.open('GET', this.keep_alive_path, true);
        request.responseType = 'json';
        request.send();
    }
}

Helper method:

app/helpers/application_helper.rb

  def auto_session_timeout_settings
    if user_signed_in?
      data_action = [
        'keypress->auto-session-timeout#keep_alive',
        'scroll@window->auto-session-timeout#keep_alive'
      ]

      {
        data: {
          controller: 'auto-session-timeout',
          'ast-frequency': 5,
          'ast-active-path': active_path,
          'ast-keep-alive-path': keep_alive_path,
          action: data_action.join(' ')
        }
      }
    else
      {}
    end
  end

View:

app/views/layouts/application.html.slim

[...]
body *auto_session_timeout_settings
  [...]

Routes:

config/routes.rb

[...]
  devise_for :users, controllers: { sessions: "users/sessions" }

  devise_scope :user do
    get "active", to: "users/sessions#active"
    get "keep-alive", to: "users/sessions#active"
    # Not used - just for completion
    # get "timeout", to: "users/sessions#timeout"
  end
[...]

Application Controller (thanks to #16 )

[...]
  # has to be after auto_session_timeout so that prepend will not be overwritten.                                                                                                                                  
  # Required: Login will not work without
  # > Can't verify CSRF token authenticity.
  protect_from_forgery with: :exception, prepend: true
[...]

Inactivity is not detected

I'm getting the active heartbeat every 1 minute.

def auto_timeout 2.minutes end

I never get a timeout. Where should I look for clues?

I tried both:
def timeout signout_user # my existing method end
def timeout render_session_timeout end

Rails 5.0.7

ActionController::InvalidAuthenticityToken

When the app does timeout as expected and redirects to the login route I invariably get an ActionController::InvalidAuthenticityToken when trying to login and create a session. Any ideas?

Routes:
devise_scope :user do
match 'active' => 'users/sessions#active', via: :get
match 'timeout' => 'users/sessions#timeout', via: :get
get 'login', to: 'devise/sessions#new'
end

Log:
Started GET "/login" for 127.0.0.1 at 2017-06-07 10:16:23 -0400
Processing by Devise::SessionsController#new as HTML
Rendering devise/sessions/new.html.erb within layouts/application
Rendered devise/shared/_links.html.erb (0.9ms)
Rendered devise/sessions/new.html.erb within layouts/application (23.3ms)
Rendered layouts/_messages.html.erb (0.3ms)
Rendered layouts/_navigation.html.erb (3.9ms)
Completed 200 OK in 267ms (Views: 265.3ms | ActiveRecord: 0.0ms)

Started POST "/users/sign_in" for 127.0.0.1 at 2017-06-07 10:19:50 -0400
Processing by Users::SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "user"=>{"email"=>"[email protected]", "password"=>"[FILTERED]"}, "commit"=>"Log in"}
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 2ms (ActiveRecord: 0.0ms)

protect_from_forgery exceptions in auto_session_timeout method raises error with `raise_on_missing_callback_actions = true`

Steps to reproduce

  1. Create rails 7.1.x app
  2. Ensure config.raise_on_missing_callback_actions = true set
  3. Add auto_session_timeout to controller
  4. Load a page

Expected results
Page loads

Actual results
Unknown action returned (404 status)

Notes

Question
Since active and timeout are documented to require get method, can we remove the protect_from_forgery call altogether? Is it required for get? This would allow us to run application with raise_on_missing_callback_actions = true

undefined current_user

Hi,

In installed the auto-session-timeout gem and getting this error from the application.html.erb where this code was inserted.

<% if current_user %> <%= auto_session_timeout_js %> <% end %>

ActionView::Template::Error (undefined local variable or method `current_user' for #<#Class:0x007fc05c25ecd8:0x007fc04615b658>):

is there a location where the current_user variable is defined. I used the instructions given to implement the timeout feature.

Thank you

Carmelo

No route matches

I had everything working or so i though.. Site worked fine until i entered Solidus.

routes.rb
` mount Spree::Core::Engine, at: '/ecommerce'

get 'active' => 'sessions#active'
get 'timeout' => 'sessions#timeout'

`

When going into anything in Solidus it would throw:
ActionController::UrlGenerationError in Spree::OrdersController#edit
No route matches {:action=>"active", :controller=>"sessions"}

I was able to get around this by adding these lines to application_controller.rb

` def timeout_url
'/timeout'
end

def active_url
'/active'
end`

Reset time out when there is mouse movement or input

I've got your gem up and running, but when I move the mouse, enter something still on the same page, does it still count as idle? because when I'm on the same page more than the specified timeout time, even when I'm typing something and moving the mouse, I still experience auto timeout and logged out automaticaly. Thank you!

undefined method `zero?' for "/timeout":String (NoMethodError)

Hi,

When I use jquery-auto-session-timeout-0.5.1 with Jruby 1.5.1,

I got the following error during the building of my Jruby application

D:/My Projects/ruby/ama_etoms_v1/config/routes.rb:100: undefined method zero?' for "/timeout":String (NoMethodError) from C:/NetBeans 6.9.1/ruby/jruby-1.5.1/lib/ruby/gems/1.8/gems/actionpack-2.3.9/lib/action_controller/routing/route_set.rb:227:indraw'
from D:/My Projects/ruby/ama_etoms_v1/config/routes.rb:1
from D:/My Projects/ruby/ama_etoms_v1/config/routes.rb:171:in load' from C:/NetBeans 6.9.1/ruby/jruby-1.5.1/lib/ruby/gems/1.8/gems/activesupport-2.3.9/lib/active_support/dependencies.rb:171:inload_with_new_constant_marking'
from C:/NetBeans 6.9.1/ruby/jruby-1.5.1/lib/ruby/gems/1.8/gems/activesupport-2.3.9/lib/active_support/dependencies.rb:547:in new_constants_in' from C:/NetBeans 6.9.1/ruby/jruby-1.5.1/lib/ruby/gems/1.8/gems/activesupport-2.3.9/lib/active_support/dependencies.rb:171:inload_with_new_constant_marking'
from C:/NetBeans 6.9.1/ruby/jruby-1.5.1/lib/ruby/gems/1.8/gems/actionpack-2.3.9/lib/action_controller/routing/route_set.rb:287:in load_routes!' from C:/NetBeans 6.9.1/ruby/jruby-1.5.1/lib/ruby/gems/1.8/gems/actionpack-2.3.9/lib/action_controller/routing/route_set.rb:287:ineach'
... 10 levels...
from C:/NetBeans 6.9.1/ruby/jruby-1.5.1/lib/ruby/gems/1.8/gems/rails-2.3.9/lib/commands/server.rb:84
from C:/NetBeans 6.9.1/ruby/jruby-1.5.1/lib/ruby/gems/1.8/gems/rails-2.3.9/lib/commands/server.rb:3:in `require'
from script\server:3

When I commented the line
map.timeout '/timeout', :controller => 'sessions', :action => 'timeout'
the build was a success. But the auto session time out doesn't works.

I am using the autosessiontimeout gem, as given in the read me file.

Please have look on this issue..

Make compatible with Rails 7.1

With the recent release of Rails 7.1, this gem now needs updating so that it is compatible.

I've created a Pull Request #42 to add Rails v7.1 to the testing matrix (as well as added tests for newer versions of ruby too)

auto_session_timeout value keeps going up

Hi,

If I don't set auto_session_timeout to the same frequency of the JS ping to /active, the session[:auto_session_expires_at] just keep going up and is never reached, even if no action is happening.

Any idea?

Can't get session params needed for redirection after timeout

I have a Rails application with two mountable engines: A and B. Both engines share the same authentication system based on Devise. I also use the atuo-session-timeout gem, overriding the active and timeout methods as follows:

  # GET user_sessions/active
  #
  # Returns the active status of the user.
  def active
    response.headers["Etag"] = nil # clear etags to prevent caching
    render(plain: current__user.present?, status: 200)
  end

  # GET /api/v2/user_sessions/timeout
  #
  # Redirects to the timeout path.
  def timeout
    params_h = ... # get params from cookies
    flash[:error] = I18n.t('errors.api.timeout')
    redirect_to(index_path(params_h))
  end

When a timeout occurs and the timeout method is called, I need the following parameters to redirect to the correct page:

  1. login_source: this is stored in the session and determines from which application the current user logged in (A or B).
  2. customer: the name of the customer. Different customers have different stylesheets. This can be obtained from the current user.
  3. location: which of the customer's locations was used. This can also be obtained from the current user.

However, when the timeout method is called in my sessions controller, the session has already been killed. This leaves me only one option: to store the parameters in the cookies and retrieve them from there to redirect to the correct login page.

Ideally, I would like to get these parameters from somewhere else, as cookies are being restricted more and more. In the future, if the site is embedded in an iframe, I won't even be able to get the parameters from the cookies, as they will be considered third-party cookies (see Article). This is also the case if an user has blocked all cookies in their browser.

auto-session-timeout Working fine but problem with locale(en | ja)

Whenever I change language, like -from english to Japanese ,everything works fine.But when I click any of the options on the menu,It gets converted to english again and When I click again on any other options it again gets converted to Japanese.

(1) SmartEms _ プロジェクト (2) SmartEms _ Members
(3) SmartEms _ ダッシュボード (4) SmartEms _ Reports

routes.rb
scope "(:locale)", locale: /en|ja/ do
devise_for :users, controllers: { sessions: 'users/sessions' }
devise_scope :user do
match 'active' => 'users/sessions#active', via: :get
match 'timeout' => 'users/sessions#timeout', via: :get
end
end

application_controller.rb
before_action :set_locale
auto_session_timeout 30.minutes
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
def default_url_options(options = {})
{ locale: I18n.locale }
end

application.html.erb
<%= auto_session_timeout_js %>

sessions_controller.rb
def active
render_session_status
end
def timeout
flash[:notice] = "Your session has timed out."
redirect_to "/users/sign_in"
end

Problem With this link

Request URL: http://localhost:3000/active

It should be

Request URL: http://localhost:3000/ja/active
or
Request URL: http://localhost:3000/en/active

update the gem

  • can you please update the gem to be 0.9.3?

thanks a lot!

auto_session_timeout_js is not defined

I get the error auto_session_timeout_js is not defined after I added this into my layout:

<% if (current_account) %>
   <%= auto_session_timeout_js %>
<% end %>

I'm using Rails 4.2.0
I think I have everything else set up correctly - do you have any suggestions?

One more edit, I installed jquery-auto-session-timeout but putting it in my Gemfile and running bundle install. However, I still get the same error.

Thanks!

Gem Load Error is: undefined method `hide_action' for ActionController::Base:Class

Was able to install it "successfully" but when I try to start my application it runs into issues.

jdms-mm:pdlog User$ ruby -v
ruby 2.2.6p322 (2016-04-29 revision 54815) [x86_64-darwin15]

jdms-mm:pdlog User$ rails -v
Rails 5.0.0.rc1

jdms-mm:pdlog User$ bundler -v
Bundler version 1.12.4

jdms-mm:pdlog User$ gem install auto-session-timeout
Successfully installed auto-session-timeout-0.9.2
Parsing documentation for auto-session-timeout-0.9.2
Done installing documentation for auto-session-timeout after 0 seconds
1 gem installed

jdms-mm:pdlog User$ rails c
...
/Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/bundler-1.12.4/lib/bundler/runtime.rb:89:in rescue in block (2 levels) in require': There was an error while trying to load the gem 'auto-session-timeout'. (Bundler::GemRequireError) Gem Load Error is: undefined methodhide_action' for ActionController::Base:Class
Backtrace for gem load error is:
/Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/auto-session-timeout-0.9.2/lib/auto_session_timeout.rb:5:in included' /Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/auto-session-timeout-0.9.2/lib/auto_session_timeout.rb:40:ininclude'
/Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/auto-session-timeout-0.9.2/lib/auto_session_timeout.rb:40:in <top (required)>' /Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/activesupport-5.0.0.rc1/lib/active_support/dependencies.rb:293:inrequire'
/Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/activesupport-5.0.0.rc1/lib/active_support/dependencies.rb:293:in block in require' /Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/activesupport-5.0.0.rc1/lib/active_support/dependencies.rb:259:inload_dependency'
/Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/activesupport-5.0.0.rc1/lib/active_support/dependencies.rb:293:in require' /Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/auto-session-timeout-0.9.2/lib/auto-session-timeout.rb:1:in<top (required)>'
/Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/bundler-1.12.4/lib/bundler/runtime.rb:86:in require' /Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/bundler-1.12.4/lib/bundler/runtime.rb:86:inblock (2 levels) in require'
/Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/bundler-1.12.4/lib/bundler/runtime.rb:81:in each' /Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/bundler-1.12.4/lib/bundler/runtime.rb:81:inblock in require'
/Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/bundler-1.12.4/lib/bundler/runtime.rb:70:in each' /Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/bundler-1.12.4/lib/bundler/runtime.rb:70:inrequire'
/Users/jdm/.rvm/gems/ruby-2.2-head@pdlog/gems/bundler-1.12.4/lib/bundler.rb:102:in `require'
...

Rails 7 support

Rails 7 was released a few weeks ago :)

The gemspec currently requires that actionpack be lower than version 7. Could this be bumped up?

Rails 6 Zeitwerk Warning

DEPRECATION WARNING: Initialization autoloaded the constants ActionText::ContentHelper and ActionText::TagHelper.

Being able to do this is deprecated. Autoloading during initialization is going
to be an error condition in future versions of Rails.

Reloading does not reboot the application, and therefore code executed during
initialization does not run again. So, if you reload ActionText::ContentHelper, for example,
the expected changes won't be reflected in that stale Module object.

These autoloaded constants have been unloaded.

Please, check the "Autoloading and Reloading Constants" guide for solutions.
(called from <top (required)> at XXX

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.