Topic: RESTful Authentication Redirects

I have a bunch of articles which are basically all teasers to the public user. Once you log in you get full access and can read the whole thing. The login form is on the same page as the article, so you can log in right on the spot.

It all works splendidly except that when a user logins in, they are redirected to the homepage, instead of the article they were trying to read.

Now, out of the box, RESTful auth is supposed to support this behavior. Browsing through the authenticated_system file in the lib folder, I see these methods

# Store the URI of the current request in the session.
    # We can return to this location by calling #redirect_back_or_default.
    def store_location
      session[:return_to] = request.request_uri
    end
   
    # Redirect to the URI stored by the most recent store_location call or
    # to the passed default.
    def redirect_back_or_default(default)
      session[:return_to] ? redirect_to_url(session[:return_to]) : redirect_to(default)
      session[:return_to] = nil
    end

In my sessions create action I am definitely calling the method correctly

if logged_in?      
      redirect_back_or_default('/')
      flash[:notice] = "You have logged in successfully."
    else
#,,,,

But it always redirects to the homepage no matter where I am.

I tried to get clever and simply redirect to the request uri

redirect_to request.request_uri

But that bombs out with "No action responded to show", which is weird because I debug request.request_uri in my view and it clearly shows up as a string containing the relative URL, but for some reason my controller does not like this.

Any bright ideas are certainly welcome

Re: RESTful Authentication Redirects

I don't know why the request_uri method doesn't work but I do know 'redirect_back_or_default' only works after you call the store_location method (which is handled by the login_required filter normally.)

From lib/authenticated_system.rb:

# We can return to this location by calling #redirect_back_or_default.
def store_location
  session[:return_to] = request.request_uri
end
# Redirect to the URI stored by the most recent store_location call or
# to the passed default.
def redirect_back_or_default(default)
  session[:return_to] ? redirect_to_url(session[:return_to]) : redirect_to(default)
  session[:return_to] = nil
end

What you could do is call store_location every time people look at a page from which they can log in (provided they aren't logged in already), that way they would always be redirected on login.

Re: RESTful Authentication Redirects

Good catch marsvin!

I didnt realize that the only place that calls the store_location method is the access_denied method.

Now I'm just curious of the best way to store location on the desired pages... a before filter maybe?

or should I put something in my view files?

Re: RESTful Authentication Redirects

How about passing the article id as a hidden field in the login form and then you can set up the store_location the same time you handle the login.

Railscasts - Free Ruby on Rails Screencasts

Re: RESTful Authentication Redirects

That sounds interesting Ryan..I'm just not sure of the best way to do this, especially since I'm using SEO-friendly permalink URLs

Re: RESTful Authentication Redirects

In the login form on the article pages you can do this:

<%= hidden_field_tag :article_id, @article.id %>

And then in your sessions controller create action just check if it's passed and set the location:

# in sessions create action
if params[:article_id]
  session[:return_to] = article_path(params[:article_id])
end

Railscasts - Free Ruby on Rails Screencasts

Re: RESTful Authentication Redirects

I just tested this out and it wasnt working, but I finally tweaked it to work with my permalinks

= hidden_field_tag :article_id, @article.permalink

Ryan saves the day again!

(We need to design a spandex uniform for you or something)

Re: RESTful Authentication Redirects

I am actually having an issue with this. Basically to call store_location, you just call the actual method so it looks something like this:

if logged_in?      
  # redirect_back_or_default('/')
  ## you can use just
  store_location
  ## or you can use
  # request.request_uri
  flash[:notice] = "You have logged in successfully."
else
...

Now here is the problem: from the session controller to the new action, it redirects to the create action in the sessions controller. The return uri is always :controller => 'session', :action => :create. It's trying to bring you back to the action view for create.rhtml which does not exist. If you create an empty create.rhtml, then you dont get error bombs but now that is not really the intended function/result.

What is the workaround for this? Any pointers? I mean if I'm thinking javascript, I can just do history.back(-2);. Is there a Ruby way for that?

=====================
Sam G.

Re: RESTful Authentication Redirects

shajused wrote:

What is the workaround for this? Any pointers? I mean if I'm thinking javascript, I can just do history.back(-2);. Is there a Ruby way for that?

Nope, you can do "redirect_to :back" but that is only the previous request and can't always be relied upon.

However I don't understand your problem. Do you have the same circumstances as in this thread? Where you need the login form embedded on a page and you need to redirect back after logging in? If so, you shouldn't be doing store_location at all. Just set the URL directly as I showed in the code.

If it's not the same circumstances, I recommend creating a new thread for this problem and going into more detail.

Railscasts - Free Ruby on Rails Screencasts