I wonder if it's possible to attach a middleware/function for a specific route like express js. http://expressjs.com/en/guide/using-middleware.html#middleware.application
In my understanding, it seems that flask(WSGI) middleware applies to all request.
The equivalent pattern is a route decorator. Flask has some docs about it. It is pretty flexible, you can validate anything in HTTP request and change the response based on that.
For example, Flask-Login has the #login_required decorator to add a user authentication step before the route is called.
Related
Django has two approaches.
Regular DRF restricts user on Middleware level. So not logged in user doesn't reach anything.
GraphQL, on contrary, uses "per method" approach. So middleware passes all the request and each method. But afterward method calls decorator.
I want to implement 1st approach but for GraphQL. But in that case I need to open path for login mutation. How can I extract mutation name from payload?
If you want restrict a GraphQL API endpoint to Django logged in users, you can do it by extending GraphQLView with LoginRequiredMixin
from django.contrib.auth.mixins import LoginRequiredMixin
from graphene_django.views import GraphQLView
class PrivateGraphQLView(LoginRequiredMixin, GraphQLView):
"""Adds a login requirement to graphQL API access via main endpoint."""
pass
and then adding this view to your urls.py like
path('api/', PrivateGraphQLView.as_view(schema=schema), name='api')
in the usual way as per the docs.
If you don't want to protect your entire API, you can create another schema and endpoint for the unprotected queries and mutations, which allows a clear separation between each. For example in urls.py:
path('public_api/', GraphQLView.as_view(schema=public_schema), name='public_api')
Note that every API endpoint must have at least one query to work or it will cause an assertion error.
Not sure if it serves your purpose, but I've used the following library which used JWT authentication with graphene similar to how JWT with DRF works!
https://github.com/flavors/django-graphql-jwt
I used Django Tastypie to build my api and i'm thinking in the correct way to create a login form so the user can login in the application, right now what I do is send a GET request with username/password he submited in the form as filtering options, but i'm pretty sure thats not secure at all. How can i do the same using POST request?
When i open the console with firebug:
GET URL/app/api/v1/user/?email=USER&password=PASS
Api-Auth and Content-Type are on the header.
#leosilvano
Don't handle user authentication and authorization using angular js not that its impossible but just that its not too secure and implementing also take some effort when Django's provides something which far easy than this.
I happen to be using django + angularjs + tastypie (REST API ). If you like take a look at my way of implementation.
Include your index.html of the angularJs in your templates ( Django Templates ) and place your directives, controllers, js, css and etc in the static folder ( Django Static ). Make your API calls after the auth processes. This will work seamlessly and you will run into less issues as well.
Reasons:
user_auth models becomes so handy while registering and logging in using templates and you don't need to sweat trying to write your own authentication which i'm sure you have to do when you go with Angular Js login auth implementation.
Use of decorators like for a view lets say "profile" if you need to check if the user is logged in all you need to do it something like the following
#login_required(login_url='/login/')
def profile(request):
return render_to_response('profile.html')
Passing password through "GET" is bad .. and passing auth values through "POST" and getting it via JSON .. is also not a good idea. Because you will be susceptible to middle-man attacks ..
Remember you have to take measures for CORS requests when using Angularjs for login since anyone can view the json response and they will be able to reproduce the same structure. Implementing Perm-Mixins and Groups is way more easier when using Django templates.
Handling exceptions like 404 or if you want to handle only post requests and thereby take user to a custom page ( actions like redirect ) becomes difficult. I am aware of SPA's but still if there happens to be redirection .. in my case i needed to redirect to another site. Following shows how simple it can be achieved including http statuses.
if request.method != 'POST':
return HttpResponseNotFound(render_to_response('404.html', { 'message' : 'Only POST Requests are allowed for authentication process.', 'baseurl' :request.build_absolute_uri('/').rstrip('/')}))
Solution:
Use Angular Js and REST (Tastypie) interaction to happen after you login. Use Django template for login authorization. Make use of the django modules .. it saves a lot of time.
If you still want to login using REST API .. by send post to django .. please take a look at the following post
How can I login to django using tastypie
You can POST data using the $http module
Just do:
$http.post(url, data)
Always send authentication data through https or your password will be sent in clear text.
I'm using django with apache mod_python. I authenticate users via the basic auth handler (django.contrib.auth.handlers.modpython) [1]. My views get only an instance of AnonymousUser passed in request.user. What am I doing wrong?
[1]: it's an API that is https only, so it shouldn't be a security problem.
I figured it out by myself now: In case you need to do something user specific in a view that is exposed via basic authentication don't let apache handle authentication for you.
If you want HTTP Basic Authentication for all your views write (or get) a Middleware. If, like me, you want to expose only a few views via basic auth create a decorator.
http://djangosnippets.org/snippets/243/ is a good start.
I'm attempting to expose a single API call using three different authentication mechanisms: django's login_required , HTTP basic auth, and OAuth. I have decorators for all three but can't quite figure out how to have them all get along smoothly.
The required logic is to allow access to the view if any of the decorators / authentication mechanisms are valid for the user's request - basically an OR. However, if I simply include all three decorators then they all want to be satisfied before letting the request through - an AND.
What's a good way to deal with this?
I'm not sure you can. Suppose the user isn't logged in: if using login_required the server would redirect to a login form, whereas using basic auth, the server would return a 401 error page with a WWW-Authenticate response header. Which of these do you want to happen? I don't see how it could be both.
Can a middleware check to see if a value is in the url, such as an image id ("/image/152/"), and if it is then do some checks to make sure the current user has permission to view that image and if not redirect to another url?
I had to roll my own permissions for this site I am working on and I don't want to clog up almost every view I write for the whole site with the same code, so I thought a middleware would be a good idea for this, but I'm not sure how to go about doing it.
Yes, this is possible. The django middleware docs for process_request indicate that:
def process_request(self, request)
request is an HttpRequest object. This method is called on each request, before Django decides which view to execute.
process_request() should return either None or an HttpResponse object. If it returns None, Django will continue processing this request, executing any other middleware and, then, the appropriate view. If it returns an HttpResponse object, Django won't bother calling ANY other request, view or exception middleware, or the appropriate view; it'll return that HttpResponse.
The HttpRequest object has a path attribute that will give you the URL that was requested.
If you prefer, however, note that you can also extend Django's system for authentication backends to populate the user in the request with permissions based on any arbitrary criteria, such as perhaps your hand-rolled permissions scheme. This way, you can leverage the default authentication decorators (#permission_required and #user_passes_test), and other apps/the admin site will be able to honour your permissions as well. The User object and permissions created do not need to reside in Django's user/permission tables, and can be created virtually on login; I've had a fair amount of success with this.
See Writing an authentication backend if this appeals.
If you implement authorization (Permission system) in middleware, you will end up with two options:
Check URL and allow to access
Check URL and reject access
If your requirement is that much simple, it is fine, since you don't have to touch views.
But in general, Permission system is much complex than that, for example:
User can access FOO/show_all/
But, he can't see or access foo instance, i.e, FOO/show/foo_1/
Since, he can't access foo_1 instance, we should not show them in show_all
(all foo instances)
If you want implement above 3 together, I suggest you write your own custom authorization backend for Django. All you need to do is implement few methods (your specific logic) and attach as backend.