2
votes

I am using Devise and Omniauth for facebook authentication. I am trying to redirect the User to the previous page after the User logs in either with Devise(regular) or Omniauth(fb).

"request.referer" works when the user uses the dropdown login on my navbar, but when the user tries to log in through the "http://localhost:3000/users/sign_in" url, "request.referer" gives me back an infinite loop error.

Here is the sequence. The problem is in (d). (a) Unlogged-in User clicks Vote up for Mission. (b) User is redirected to the "users/sign_in" url, because of the "before_filter :authenticate_user!" in the Missions Controller. (c) User signs in either by typing in username/pword, or clicking Facebook icon. (d) User should be redirected back to previous page, with the function VoteUp completed, but instead gives routing error => when I go back and refresh the page, the user is signed in, so I know it's just a problem with routing

MissionsController.rb

class MissionsController < ApplicationController
 before_filter :authenticate_user!, :except => [:show, :index] 

 def vote_for_mission
   @mission = Mission.find(params[:id])
   if @mission.voted_by?(current_user) 
     redirect_to request.referer, alert: 'You already voted on this mission.'
   else
     @mission.increment!(:karma)
     @mission.active = true
     @mission.real_author.increment!(:userpoints) unless @mission.real_author.blank?

     current_user.vote_for(@mission)
     redirect_to request.referer, notice: 'Your vote was successfully recorded.'
   end
 end

ApplicationsController.rb

class ApplicationController < ActionController::Base

  protect_from_forgery                                                                                                                                    
  def after_sign_in_path_for(resource)
    sign_in_url = "http://localhost:3000/users/sign_in" || "http://onvard.com/users/sign_in" || 
    "http://www.onvard.com/users/sign_in" #url_for(:action => 'new', :controller => 'sessions', :only_path => false, :protocol => 'http')                                            
    if (request.referer == sign_in_url)                                                                                                                     
      env['omniauth.origin'] || request.env['omniauth.origin'] || stored_location_for(resource) || getting_started_path || root_path      
    else
      request.referer
    end
  end

The User is redirected to the "getting_started_path," which I put so I knew the previous options weren't working. The 'else' case, which is the dropdown login form I created with jquery, redirects the user to the previous page perfectly fine, but when I try to put the request.referer in the 'request.referer==sign_in_url' case, it gives me an infinite loop.

How would I redirect the User to the previous page even when the user logs in through the 'users/sign_in' url??

2
Comment on the Ruby code: sign_in_url = "http://localhost:3000/users/sign_in" || "http://onvard.com/users/sign_in" || "http://www.onvard.com/users/sign_in" #url_for(:action => 'new', :controller => 'sessions', :only_path => false, :protocol => 'http') will automatically be the same as sign_in_url = "http://localhost:3000/users/sign_in". - Andrew Grimm

2 Answers

0
votes

You can't simply redirect back, because the sign_in_url is meant to only accept users that are not logged in, and after logging in your app is sending a logged in user back to that page.

If you need to redirect the user to a specific location after login you should store the original place the user tried to go before the redirect to the login page, then after the login, check if the user should go to a different place after logging in, and redirect him there.

0
votes

I'm addressing this reply to future generations who use devise and have the same problem of OP: you should be able to solve it by using #stored_location_for, that returns the path that the user wanted to reach before being redirected to the sign in page.