Proper way to setup ldap auth with aiohttp.web - python

I'm looking for solution how to setup domain authorization with aiohttp.
There are several ldap librarys, but all of them blocks event loop, plus i don't have clear understanding about user authorization with aiohttp.
As i see i need session managment and store isLogdedIn=True in cookie file, check that cookie at every route -> redirect at login handler, and check key in every template? It seems very insecure, session could be stolen.

You may call synchronous LDAP library in thread pool (loop.run_in_executor()).
aiohttp itself doesn't contain abstractions for sessions and authentication but there are aiohttp_session and aiohttp_security libraries. I'm working on these but current status is alpha. You may try it as beta-tester :)

Related

Flask Logout All Sessions of a Specific User

When logging out a user with Flask-Login, is there a way to log out all sessions that user may have (Ex: in different browsers, different devices, etc)?
Flask-Login stores user_id in Flask session which is client-side session, the data stores in cookie file in users browser. Hereby you can't delete cookies in all devices and browsers of the client.
Nevertheless you can use server-side sessions instead with the help e.g. Redis and Flask-Session extension for Flask. Server side session will solve problem with removing or manipulating (imagine admin gave or removed user's rights) user session simultaneously for any user's browser or device.
https://pythonhosted.org/Flask-Session/
As Artiom said in his answer, Flask-Login by default uses Flask session which is client side, and you won't be able to delete all those cookies from other clients.
However, there is a way to prevent other clients from logging in. Flask-Login relies on user_loader callback function to fetch the user from your cache, this function gets called on every HTTP request coming from the user's client.
What you can do is on logout, you delete this particular user from this cache. That way when any client (phone, other browser,etc..) used by this user try to access your page. Flask-Login won't find the user in the cache and will redirect them to the login page.

How is Flask-Login's request_loader related to user_loader?

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?
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
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.
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.)

How do I protect urls I use internally for push queues in Google App Engine?

I'm running Flask on GAE, and I'm working on implementing a push queue to run tasks for me in the background. Because GAE's push queues work by scheduling and sending http requests to my flask server, I'm concerned about my users guessing the urls I designated for internal use with my push queue. I thought about having the push queue send a secret key along with the requests, and have my server only execute the job if the key included in the request is correct, something like this:
taskqueue.add(url='/worker', params={'super_secret_key': 12345})
But I'm wondering if there's a more secure / better way to do this?
Thanks!
You can protect your task urls by configuring them in app.yaml to use admin login
- url: /worker
......
login: admin
here is another way to do it that i think is more efficient.
you can take advantage that appengine removes some request headers from external (ie users) requests. but it doesnt if the request is internal:
http://googlecloudplatform.blogspot.com/2015/07/Unit-Testing-cron-handlers-in-Google-App-Engine.html
look where it says: "Instead, the Cron Service sets a special request header -- X-AppEngine-Cron: true. This is a header that application code can fully trust, since App Engine removes such headers if they’re set in an external request."
you should be able to use the same principle when making yours calls. see these request headers that google sets on taskqueue calls:
https://cloud.google.com/appengine/docs/python/taskqueue/overview-push#task_request_headers
you wont need the admin login anymore, and note that its even more secure because it will only be possible to call from a task queue (thus would require a code change to tamper)

Spotify without Redirect URI?

I'm using Spotipy to get some spotify data from an authorized user but I can't understand how to authorize my account.
Am I correct in thinking that a server is required that hosts something at http://www.myapp.com/callback ? What needs to be returned? Maybe I'm completely missing something here... I'm very confused by the whole required redirect URI thing...
I am trying to make a program, without website, so how should I handle authorization? What exactly should the redirect URI do?
Thanks
Edit:
Using http://localhost:8888/callback as my redirect URI now and that works. I'm not even sure why since nothing is running on that port.
Disclaimer: I know nothing about Spotify's API. But I have worked with similar APIs in the past (or even designed them). What I assume is that they use some kind of OpenID/OAuth authorization mechanism.
The very nature of these APIs is that they work through the browser! The idea is that MyApp doesn't have your actual Spotify credentials, but instead some signed token it can use.
To communicate this token to the MyApp, there are the server-callbacks, outlined in your question. Because all the browser can do is to redirect to a special URL you provide, with some info added.
So there are conceptually two ways to deal with this:
the easy, server-based one: you in fact register a myapp.com. When your app tries to authorize with spotify, it first creates a unique resource (myapp.com/authrequests/HASH-NUMBER), and communicates this as callback. Then it goes through the motions of making spotify authorize it, and once these are finished, there will have been a call to myapp.com/authrequests/HASH-NUMBER/ADDITIONAL-INFO. So while your app is waiting for this to happen, it has to poll (or open a websocket and listen to that) myapp.com. Complicated? Wait, it gets better!
the harder, OS-dependent one: you write an application that registers itself as protocol-provider with your browsers. E.g. my company does that with the protocol "ableton". Thus we can make the browser generate "ableton://AUTHORIZATION-REQUEST-RESULT" URLs which will then be communicated through Browser and OS to the running application, and thus you receive the necessary secret.
HTH

How to create an API with a "remember me" function in Flask?

I'm going to build an API in Flask for a (to be created) app which will be built using PhoneGap. In the API many calls will need authentication.
To get into the topic I was reading this tutorial on creating authentication for a Flask-built API. In this tutorial they first show how a user can use basic password authentication for every call, after which token based authentication is introduced.
As far as I understand, the client who calls the API should simply get a token and authenticate every subsequent call with that. In the meantime, the client should keep track of time and either get a new token every 9 minutes (before the old token expires) or simply keep on calling with the token until the client gets an Unauhorized Access message. Am I understanding this correctly?
Moving on, I wonder how it works with Apps on which you login on your phone and then are always logged in whenever you open the app (like for example the Facebook app). This is obviously more convenient to the user than always needing to provide the username/password and I would like to implement something like that as well. I wonder though; how is a permanent logged in feature like this implemented on the server side? Is it done by providing the password and username for every call, or using a never expiring token, or yet a different way?
All tips are welcome!
I've done what you want to do with:
Flask-security https://pythonhosted.org/Flask-Security/:
To manage users and permissions.
Flask-oauth-lib https://flask-oauthlib.readthedocs.org/en/latest/:
Provide oauth functionnality.
So, you have to take a look at Oauth flow, implements a user backend (like Flask-security) and implements an oauth server (with flask oauth lib for example) and bind it to your user backend.
After that, it's oauth standard flow. You just have to give the right token on each api calls and TADA !
With this way you can also, if you want, give access to your api to third-party app thanks to oAuth :)

Categories

Resources