I have a case where two requests(iframes) are made by browser to a rails app (rails 3.2, devise 2.2.0), both initiate sign in (through SSO) and then render the requested page. Problem is that there is a race condition for session[:user_return_to]
and both of the pages render same page so one of the iframes end up rendering wrong page.
This is the flow of the app right now
authenticate_user!
method is called and devise redirects to /users/sign_in
pageSessionsController#new
processes the request and instead on rendering it redirects to /sso/new
/sso/create
which sign user in (in devise) and redirects to requested pageOn step 2, I can pass a URL as a param to /sso/new
and that param will be returned back to me during step 3. Problem is that referrer is already lost when I'm in SessionsController#new
. All I have there is session[:user_return_to]
which already has wrong value for one of the iframes (session is shared and race condition occurs).
I was wondering if the referrer can be passed on somehow through warden failure. I was not able to see if there is a hook to pass it as param or header through warden when executing authenticate_user!
before filter. During that request I have referrer but warden doesnt preserve it when it redirects to /users/sign_in
.
I was able to solve this problem by using custom failure app for warden.
I used request.original_fullpath
in redirect_url and it worked.
here is my failure class
class CustomDeviseFailure < Devise::FailureApp
def redirect_url
if sso_enabled?
sso_path(return_to: request.original_fullpath)
else
super
end
end
def sso_enabled?
true
end
end