Redirect after login with Flask

Hopefully this will be useful for anyone in the same situation I was in a few hours ago - Google definitely didn't help with this one.

If you want to redirect to a page after you've logged into a Flask webapp, there's seemingly a pretty nice way of doing it. The @login_required decorator is built into Flask-Login, and it does the job of controlling access to views that require authenticated users.

However, in my case, it wasn't feasible. My authentication system involved redirects to external OAuth providers (Facebook and Twitter), and so I couldn't see an easy way of passing a next=<url> parameter*.

*This would likely have been solved by using a popup instead of a redirect. However, I specifically wanted to make it work with a redirect.

I couldn't seem to make any solution with the global request object retain the 'next url' parameter - this made sense, because I was redirecting to an external page, which called back to a page on my server.

The global g object didn't work either, and after a lot of reading it turned out that g similarly didn't persist data between requests. (N.B: the documentation is really, really bad at getting this across, thank the gods for StackOverflow).

The solution I found was to import the session object from Flask. I wrote my own login_required decorator, which did much the same thing as the original, but saved request.url into session["wants_url"]. The source code for the decorator is pretty short:

def login_required(fn):  
    @wraps(fn)
    def decorated_function(*args, **kwargs):
        if current_user.is_authenticated():
            return fn(*args, **kwargs)
        else:
            session["wants_url"] = request.url
            return redirect(url_for("login"))
    return decorated_function

In my oauth_callback, in order to redirect to the requested page, I just return a redirect to session["wants_url"].

Finally, I made sure to set session["wants_url"] = "/" in my logout() function. This means if the user logs out and back in again after being redirected somewhere, they won't see the page they requested before logging in last session, they'll just be sent to the index.