I am using Django framework for my backend support for a mobile app.
I choose to use the original Django's views.py to get my API url mapping and dump JSON for response, rather than using other REST frameworks like Django REST Framwork or TastiPie.
Now if I make a cross domain HTTP Request from my mobile client app. normally I will get a 403 Forbidden error because of Django's built-in CSRF protection. It seems like it can only work when I exempt it explicitly before each function in views.py. My question is, is it safe to exempt the protection? If exempt csrf is not a good way to do, what suggestions do you have on my situation?
Thanks
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 using a combination of flask-jwt-extended for JWT authentication, and I've enabled CSRF protection, meaning for certain HTTP methods (PUT, POST, DELETE...), it is required that the value in the cookie and the HTTP header match.
This works fine for my API requests, where I just construct the HTTP request in JS with the header set correctly, but I want to use Flask-Admin, and allow access based on the JWT tokens. I did this by decorating the is_accessible function in Flask-Admin's ModelView with #jwt_optional and checking within it.
However, now when I try to perform any modifications through Flask-Admin, I get an error message from flask-jwt-extended, stating that I didn't properly include my CSRF tokens. This is true, as I'm using the default forms that come with Flask-Admin.
My question is, what is the best solution? Is it possible to disable CSRF protection only for certain paths? (And enable Flask-Admin's own CSRF protection for them?) Should I modify the views and insert JS that is triggered by the submit button but actually submits an XmlHTTPRequest? Should I implement the JWT authentication for Flask-Admin views in a different way?
I have a Python program that needs to be able to send data to my website (built with Django). This data will then be taken and displayed on a certain part of the website. The problem I'm having is that the CSRF protection built into Django blocks my POST request. From what I understand, this is usually avoided by adding {%csrf_token} to whatever form the POST request is being sent to. My problem is that I'm trying to send the POST request to a .cgi script rather than a form. Does anybody know how I could bypass the CSRF protection (preferably without removing it completely although this is an option.)
You should use the csrf_exempt decorator to avoid csrf protection in certains view.
You can read the docs for more information
In case you are using class based views, I'd recommend django-braces which uses a mixin to achieve this, as well as providing other extremely useful mixins.
I have the solution, this is more of a Why question. The problem is when running a django dev server, when i make an ajax POST request with data, if the view never looks at the POST dict, i get a urllib2 exception. "a connection was forcibly closed by a remote host" or something.
If theres no post data, it returns fine, if the data is read, not even stored, a simple
request.POST
will return ok as well. Why is this?
Thanks
I'm guessing you're not sending the csrfmiddleware_token on your post request. It's a prevention mechanism for CSRF attacks and needs to be set on all POST messages. See the documentation for details.
You need to disable CSRF protection for that view function as it is enabled by default (the CSRF Middleware).
You can opt to disable CSRF protection via two ways:
Remove the CSRF middleware and use the #csrf_protect decorator on
view functions that you wish to use the CSRF protection. Use this if you generally don't
need CSRF (eg. no forms for most of the pages). See https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#the-decorator-method
Use the #csrf_exempt decorator on the view you wish to exempt the CSRF protection from.
This is useful when you only have a few view functions that does not require CSRF
protection. See https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#exceptions
ONe of my system components is using the Basic HTTP Authrozation ( http://en.wikipedia.org/wiki/Basic_access_authentication ) for log in information. Another part of my system is running a django application which uses the 'django.contrib.auth' app for authentication.
Would code like this work?
def urlHandler(request):
if request.user.is_authenticated():
// ...
The urlHandler in this case would handle the request which has the Authorization: Basic dXNlcjpwYXNz appended to its HTTP GET. Would the django authorization backend integrate with this?
Obviously I tried the above code and it does not seem to work...
Is there a middleware that would work in this case?
Thanks
This has been asked and answered: Can I use HTTP Basic Authentication with Django?
(The answer is yes. See http://docs.djangoproject.com/en/dev/howto/auth-remote-user/ for details.)