I'm building a site on Google App Engine, running python and Django non-rel. Everything is working great for HTML and posting/reading data. But as I'm moving forward I'd like to do many of the updates with AJAX, and eventually also over mobile devices like Android and iPhone.
My pages use django non-rel and my login/logout authentication works great for the HTML. But update information sent over JSON would have to be authenticated that the user can make the changes. I see how doing authentication for just AJAX calls wouldn't be too difficult since your still hitting the website, but what about when throwing in mobile phone authentication?
So I'm new to this, where do I start?
How can I set up services on gae so I can do authenticated CRUD operations? Ideally I'd like to use the exact same REST services for ajax, android, etc.
Python makes this pretty easy, you can just create a decorator method of checking the auth and add the decorator to any method requiring auth credentials.
def admin(handler_method):
"""
This decorator requires admin, 403 if not.
"""
def auth_required(self, *args, **kwargs):
if users.is_current_user_admin():
handler_method(self, *args, **kwargs)
else:
self.error(403)
return auth_required
...
#admin
def crudmethod_update(self, *args, **kwargs):
...
Mind you, this assumes a few things about how you are grabbing user data and such but the principal is the same with any setup. The notion you may be laboring under is that ajax calls are handled somehow differently on the server, but just like any restful method you are really getting the same headers. If you can check the authentication on the standard html request you can quite literally hijack the form submission with an ajax request and get the same result back. You may want to get JSON back instead or a smaller piece of HTML and for that you want to either:
Add something you can check in the request to know that it is an ajax request and adjust accordingly.
Implement an RPC Model for handling ajax requests specifically.
For actually handling authentication you can use the google.appengine.ext users library and ride on the google accounts auth or you can write your own. Writing your own of course means implementing a session mechanism (for retaining state across the user session) and storing the passwords in a hashed and salted state for verification.
Related
I have a Django project that will ultimately consist of three apps. Two of which will be "normal" Django apps, the third is a djangorestframework app. I also plan on creating a desktop client for the project at some point.
I want the rest app to be the only entity communicating with the database. Hence I use requests to communicate with the rest endpoints from the views of the "normal" Django apps and I will do the same for the desktop client. I want all apps to be accessible only for authenticated users, so I'm using Django's authentication backend.
My question is how to pass on the authenticated user/session from the pure Django apps to the rest endpoints when using requests in the views.
I managed to authenticate on the rest API using request's HTTPBasicAuth, but that requires me to have the user's password at hand in plain text. Sure, I could create a technical user to do these requests. But that would also mean that each and every request would need to go through authentication first and that doesn't feel like the best approach.
I have tried to extract the session cookie from the request object that is provided to the views and pass it on through requests.get, but did not manage to put it into the requests.get call the right way.
As of now, using requests and the established sessions looks like my best bet, especially since that will be the way the desktop client will do things, too. So I'm currently looking for the right way to provide requests.get with the session cookie, but I'm certainly open for better solutions.
You should use tokens.
Basically any kind of authentication out of your django project should be managed with secure tokens.
And yes, authentication check should happen everytime you send a request. To make it faster, you can store tokens in memory. (You can use redis or maybe even load your db on memory or ... ) but this is the right and common way to it. Even django does this check everytime using it's builtin functions.
DRF docs recommended some few packages to manage these tokens:
DRF: Third party packages
I used knox for many projects and it's pretty good.
Basically to authenticate your users over all of your projects or microservices, you have to take the token from user, set it as header or ... for your request to the main database or authentication project.
Most of the apps use token in headers which you can simply add to all of your requests calls:
Requests docs: Custom Headers
I'm working in Flask on creating a JMML ("Join my mailing list") widget that submits data to an email marketing platform, and the platform follows an OAuth2 flow. The basic flow is:
I create access URL using a the base API URL, an API key, and a redirect URI
The program accesses this URL, and the user of the program is redirected to the marketing platform to log in and grant access.
The marketing platform performs another redirect back to the redirect URI that I provided. The URI is appended with the access token that I need to provide with app POST requests of my JMML. Here's an example of what the returned URI looks like:
http://localhost:5000/redirect_url#access_token=2C1zxo3O0J1yo5Odolypuo9DSmcI
Here's the problem I'm having: I have no idea how, programmatically, to use that final redirect url/uri as a variable in Python.I could make the user copy/paste it into a field, but there's gotta be a better way. I honestly don't even know the terminology for a redirected-redirect like this.
It's pathetic, and I'm lost, but here's what I have so far:
#app.route('/redirect_url')
def redirect_url():
# I have no idea how to actaully get the parameter out of the redirect url.
pass
I've checked the API documentation for the email marketing company's API, but they only provide code tips for handling Oauth2 in Ruby and PHP. Help!
There is a good blog post by Miguel Grinberg, where he describes how to work with OAuth in the flask application. Though I think that workflow will stay the same with any other web application.
Based on this it seems like you should be able to get the access token by getting the variable parameter from the url. I do not have your full code so i cant test, nor have I tried it with an # in the url, but this should work
#app.route('/originalurl')
#app.route('/redirect_url#<access_token>')
def show_user_profile(access_token):
if access_token:
#do work
return redirect(url_for('Anotherview')
return render_template('template.hmtl')
Otherwise we need more info on the api you are using Oauth with
I'm using the following library http://django-oauth-toolkit.readthedocs.io/ which seems to not be as well documented as I would like, and after I followed its tutorial I am able to have a working system in which I have protected views that need the authorization token, and I can access them using curl and adding the token. Curl is nice to test, but it's not practical, and I failed at developing it.
So I have a very simple protected view:
class Test(ProtectedResourceView):
def get(self, request, *args, **kwargs):
return HttpResponse('Hello, OAuth2!')
If I try to access, I will get a 403, and if I ask for the token and put it in the header using curl I can actually get it to work.
In the other hand, I have another view that gets the authorization_token, lifetime, refresh_token, .. in a dictionary (after using JSON from Django).
At this point I'm lost. I don't know what to do with the authorization token so that the user can actually use it and access to the protected view. I tried to manually add the token to the cookies but it didn't work and doesn't seem to be a good idea neither. I guess after I do something, the user can access the protected view.
Thanks.
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.)
In a web application already using django.contrib.auth for authentication, I'm looking for the "standard" approach for restricting access to Ajax services to authenticated users only.
Using the #login_required decorator won't do, because that just redirects unauthenticated users to a login page. For a service, we should probably be sending a valid, well-formed error response back -- not some login form.
This is the first approach that comes to mind:
from django.http import HttpResponse
def some_json_service_view(request):
if not request.user.is_authenticated():
return HttpResponse('{success: false}')
return HttpResponse('{success: true}')
Taking it one step farther, if I could standardize on a single response for all "not authenticated" errors, then a decorator would be nice:
from django.http import HttpResponse
def login_required_json(f):
def new_f(request):
if not request.user.is_authenticated():
return HttpResponse('{success: false}')
return f(request)
return new_f
#login_required_json
def some_json_service_view(request):
return HttpResponse('{success: true}')
Is this how everybody else does it, or is there a more accepted way it's done? Ideally, someone could point me to the django.contrib package made for this purpose.
That's an example that will work great if the AJAX services are consumed by your front-end clients only. I do that all the time, because the same design gets used for pushing all other kinds of data to the client through the response for which the client needs to perform additional actions or otherwise provide some feedback to the user. It works great when your site has mixed users, i.e. you support both anonymous and registered users.
If your building services for 3rd party vendors though, you'll either have to use OAuth, basic HTTP access authentication or digest HTTP access authentication. You do this when you know/assume that users who are performing the requests all have registered credentials. Hence, these authentication schemes allow a user to authenticate themselves if the authentication system challenges them for credentials, which they can immediately supply at hand, without manually having to enter them at a redirected login page.
So if your services have mixed users, I'd stick with what you have. Otherwise, you'll have to take up on something more elaborate, something that assumes that unauthenticated users have and can immediately supply their credentials.
In either case, I suggest you take a look at django-piston. It's like a pretty straightforward controller for parsing AJAX requests and serializing AJAX responses. Based on the supplied model and HTTP verb, it can automatically do a lot of the heavy lifting for you when exposing model access to user agents, plus it also comes packed with OAuth and HTTP access authentication.