Content

redirect back or default — you’re (probably) doing it wrong

22 October 2009 // Filed under authentication

A basic authentication scheme should go to some length to do a little bit of remembering in the event your user hits a restricted page before they are actually authenticated.

First, some context. I’ve got this in my ApplicationController:

def require_user
  unless current_user
    store_location
    redirect_to login_path
    return false
  end
end

def store_location
  session[:return_to] = request.request_uri
end

def redirect_back_or_default(default)
  redirect_to(session[:return_to] || default)
  session[:return_to] = nil
end

… which allows me to do this in any of my controllers:

before_filter :require_user, :except => [:index, :show]

… and this is cool because now my users get redirected back to where they were going after they log in. I like saving my users a click or two here and there if at all possible.

There’s a problem with this though. What happens if somehow your user POSTs to an action that is behind require user? Well request.request_uri is *not* what you want to redirect to. Why? Because redirect_to is going GET the same url that your user was trying to POST to. And if you’re being a good Rails developer and using resources then you’re just going to smack them in a face with a big fat 404, and that’s not very nice.

I actually managed to do all of this over at github earlier today by trying to comment on a commit without being logged in. Want to see it in action? (until github fixes their ways) First, go to github and logout. Then find any commit and try to make a comment, you can figure the rest out. Go ahead, I’ll wait.

What is that critter anyways? It’s like a half octopus with a lizard tail and whiskers. wut?

Anyways, here’s the simple fix:

def store_location
  session[:return_to] =
  if request.get?
    request.request_uri
  else
    request.referer
  end
end

If they’re GETing something let em keep on GETing it, otherwise take them back to where they were coming from.

This solution is only half-baked though. Any form data that the user has filled out will be gone and they’ll have to redo it. On the other hand you really shouldn’t be showing a form to an unauthenticated user that requires them to be logged in to hit it.

2009-10-22  ::  admin

  • Browse by category: authentication -

Talkback x 2

  1. Lee
    17 November 2009 @ 9:56 pm

    Good tip.

    The last part about how you shouldn’t be showing a form to an unauthenticated user that requires them to be logged in to submit the form…say a user leaves their computer while they have that form pulled up. Their session times out after 10 minutes or whatever, then the user fills out the form then hits submit thinking their still authenticated. Your change will take the user back to that form (although blank) after they sign back in. That sounds fair to me. Thanks again.

  2. Keil Miller
    20 January 2012 @ 9:55 pm

    Thank you very much for this snippet!

    Just a note:

    Rails 3.1 – Use request.url instead

    As request.request_uri has been deprecated, use request.urlinstead.

Share your thoughts







Tags you can use (optional):
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>