11
votes

I apologize in advance for asking a rather cryptic question. However, I did not understand it despite going through a lot of material. It would be great if you could shed some light on this.

What is the purpose of a request_loader in flask-login? How does it interact with the user_loader decorator?

If I am using a token based authentication system (I am planning on sending the token to my angularJS front end, storing the token there and sending that token in the authorization-token header), will I need a request_loader or will a user_loader (where I check the auth header and see if the user exists) suffice?

3
I am interested in doing the same thingZach Siegel
"I am planning on sending the token to my angularJS front end, storing the token there and sending that token in the authorization-token header" I am interested in doing the same thing! Can you clarify how you use(d) request_loader to achieve this? Does Angular's $http automatically use the same cookies as other browser requests? Do we need to do the "sending the token to my angularJS front end" part? My concern is that the session id may be sent in a different header or parameter (which is why I might need request_loader) - but won't a logged-in browser still automatically send it?Zach Siegel
Hi Zach, Sorry for the delayed response. From what I understand, you don't actually need to have both user and request loaders. A user loader is very simple, it checks the user_id that is attributed to the session and checks if that user_id exists in your user database and authenticates. A request loader checks the request authorizationheader and does the same authentication. So for most applications that have any sort of user session management, you won't need request loader. You wont have to send any tokens... Flask and angular js manage those automatically with user_loadergaleej
Hi galeej - I have found a solution that I think is even more slick. I will post it as its own answer.Zach Siegel

3 Answers

10
votes

From the Flask-Login documentation:

Sometimes you want to login users without using cookies, such as using header values or an api key passed as a query argument. In these cases, you should use the request_loader callback. This callback should behave the same as your user_loader callback, except that it accepts the Flask request instead of a user_id.

So, to answer your question, they both serve the same function for Flask-Login. They are both used to load the user. request_loader, however, is appropriate for custom logins.

Here's a great tutorial I found that utilizes request_loader to take advantage of token based authentication (The post is not my own, I'm merely sharing the link): http://gouthamanbalaraman.com/blog/minimal-flask-login-example.html

1
votes

I need to make this clear. This is the reason why you shoud use request_loader with flask_login.

There will be a lot of @login_required from flask_login used in your api to guard the request access.
You need to make a request to pass the check of auth.

And there will be a lot of current_user imported from flask_login,
Your app need to use them to let the request act as the identity of the current_user.

There are two ways to achieve the above with flask_login.

  • Using user_loader makes the request to be OK for @login_required.
    It is often used for UI logins from browser.
    It will store session cookies to the browser and use them to auth later.
    So you need to login only once and the session will keep for a time.

  • Using request_loader will also be OK with @login_required.
    But it is often used with api_key or basic auth.
    For example used by other apps to interact with your flask app.
    There will be no session cookies,
    so you need to provide the auth info every time you send request.

With both user_loader and request_loader,
now you got 2 ways of auth for the same api,
protected by @login_required,
and with current_user usable,
which is really smart.

0
votes

To verify users with Flask-Login's session_id for frontend requests through Angular, you must set the withCredentials configuration flag to true.

That is, if you are using Angular's $http.post(url,data [,config]) or $http.get(url [,config]), make sure the config object contains the property withCredentials set to true. This will instruct the browser to use its cookies in the same way it would for a full-on page visit.

For example,

$http.post('/api/login',{username:'myusername',password:'mypassword'},{withCredentials:true})

will post the data {username:'myusername',password:'mypassword'} to your site/app's /api/login route and, if you're using Flask-Login and are logged in, Flask will know.

You can set this behavior for all $http service requests by setting

$httpProvider.defaults.withCredentials=true

somewhere in your app. Currently, I have that line of code in my app.config block, which seems appropriate to me:

var myApp = angular.module('myApp');

myApp.config(function ($httpProvider) {
  $httpProvider.defaults.withCredentials = true;
  });

(Since this post is about Flask, folks may want to send form data through Angular in such a way that it can be found in request.form, which has a similar solution, fyi.)