Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple tab logout leads to InvalidAuthenticityToken on subsequent login

I've got an app that uses Devise for authentication. The login fields are on the homepage. If I open two tabs (Tab A and Tab B, and then log out of each manually (first Tab A, then Tab B), then return to Tab A and attempt to log in, I get an InvalidAuthenticityToken error.

I can then go back to Tab B and try to log in and get the error. Then back to Tab A and try to log in and get the error again. And this will happen indefinitely until you try to log in on a tab immediately after getting the InvalidAuthenticityToken error in that same tab.

I can set the following in ApplicationController:

protect_from_forgery :with => :null_session

But now the first login attempt will just return to the homepage with no indication of why your login failed (you just see the homepage again instead the InvalidAuthenticityToken error page). If you then try to login again (on the same tab) it will be successful.

And I know why it's happening: the session is being reset on sign out which is resetting the csrf_token in session. The second tab resets that token, but the first tab still has the previous one. So when the first tab submits the form the csrf_token is invalid.

Is there anything I can do here on the server side? Or am I going to have to do some crazy workaround like set something in localStorage when you logout, or open a websocket so I can be notified on the homepage that another tab has reset the CSRF token?

It may seem like a rare case to have a user with multiple tabs open go through each and manually log out, but this is just simulating the actual behavior of the site: automatically logging them out after 10 minutes. This actually happens fairly often in our app.

like image 881
Rob Cameron Avatar asked Sep 11 '14 18:09

Rob Cameron


1 Answers

Rails allows you to use the rescue_from to rescue errors of your choosing with a callback function.

You can find more information here: https://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html

Fixing a near-identical issue the top of my Sessions controller looks like this

class SessionsController < ApplicationController

  rescue_from ::ActionController::InvalidAuthenticityToken, with: :redirect_home

and my callback which is defined in the same controller looks like this

def redirect_home
   redirect_to root_url
end
like image 85
Gino Avatar answered Nov 15 '22 08:11

Gino