I am building an api for interfacing with mobile applications that requires users to login. Just using session auth gives me a csrf error. I was able to fix it by providing credentials in basic auth, but I don't think this is ideal. This will be my first time developing for mobile devices. I was planning on using cordova, and I don't know if there is a way to store credentials on the user's device, or if the session data will be automatically stored on the devices. If the session data will be stored on the mobile devices automatically, that would be the ideal route to go. Has anyone else had similar issues with DRF session auth, or advice on if this is the best route to go or not?
Update:
I was able to get the csrf error to go away by using this from another post:
from rest_framework.authentication import SessionAuthentication
class NoCsrfSessionAuthentication(SessionAuthentication):
def enforce_csrf(self, request):
return
But this seemed to cause an error with the request.data parameter. It kept returning an empty query dict.
If you want to use session auth, but are confident that you can give up CSRF protection for a given view, the
#csrf_exempt
decorator will do just that. (If you are using class-based views, check out this: https://stackoverflow.com/a/14379073/1375015)
Since you are using session based authentication, your mobile applications must be storing some kind of session cookie. Therefore, you should also be able to store the csrftoken cookie and send it along with your http requests. However, even then I had some troubles with the django CSRF protection framework in the past.
Maybe switching to token authentication is an option?
Related
I am writing a Django app that uses a 3rd-Party Authentication Service implemented with FusionAuth.
I can successfully register and login (using the authorization code flow).
However, logging out is not working. I can logout from the local Django app, but when I try to login after that FusionAuth recognizes that my access_token is still valid and just goes directly to the redirect page (the page you usually goto after successfully logging into FusionAuth).
Clearly I don't understand something about FusionAuth. I have tried both the python client and the restful API and I don't really understand what it does. According to the documentation it "...is intended to be used to remove the refresh token and access token cookies if they exist on the client and revoke the refresh token". Why then is the access_token still valid?
There seem like a couple of issues here.
First, you need to redirect the browser to https://your.fusionauth.instance/oauth2/logout and that will delete your FusionAuth SSO session. That will stop the behavior of FusionAuth redirecting you. This is because you have an SSO session cookie, and going to that URL will delete it.
Second, if you want to revoke the access token, that takes a bit more work. It is stateless. It's not the same as a session, and is distinct from the SSO session mentioned above. The access token is something you present to other APIs, not to FusionAuth. Here's some more info: https://fusionauth.io/learn/expert-advice/tokens/revoking-jwts
Hope this helps.
I am currently building an auth app that provides register, login, logout ... functionalities. Everything seems to work fine, however when I log the user in, I cannot logout, I get an Anonymous user error instead. After searching on the internet I came to the conclusion that it is not the best to build an api with sessions and instead to use tokens(JWT). With sessions I cannot test my API with tools like POSTMAN because that requires cookies (technically you can use cookies in POSTMAN though). Having said that, sessions seem to be more stable and secure so how would I go about testing my API using the sessions stored in the cookie? Thanks.
Postman supports using cookies.
when you enable it you can access it through scripts.
write a script for you login and logout to set cookies ( if it wasn't updated automatically)
you can read more about it here.
I noticed that tokens generated by Flask-WTF expire in one hour and a different one is generated every request. This will cause problems in SPAs when a page has been opened longer than an hour. XHR requests made after one hour after page-load will start failing, even if the user was active.
My workaround is to set a new token in the browser in each API call. In the server, all API responses contain a freshly-generated token:
from flask_wtf.csrf import generate_csrf
def api_response(data, error=None):
response = {"csrftoken": generate_csrf(), "data":data}
...
return make_response(jsonify(response), response_code)
In the browser we set the csrftoken on each API response.
then(function(result) {
if(result.csrftoken) csrftoken=result.csrftoken;
callback(result);
})
Is this method still safe and fast? Is there a better way to handle this? I am not too sure about using generate_csrf directly.
No, there is no other way to use the CSRF protection in Flask-WTF. When you need a CSRF token, you need to generate one and use it. There should be no problem with generating it like you do. It is still generated and validated the same way on the server, and transmitted over the same channel to the client.
I am creating an API with the Django Rest Framework. Users are still going to need to get a CSRF token to make POST, PUT, PATCH and DELETE calls. What is the best practice for the user initially getting a CSRF token? I am using TokenAuthentication. So I just need to allow the API to take and username and password and send back the Token. After that I don't need the CSRF token.
Do I have to add a step that will allow them to get CSRF token using a GET method call which will return a token?
I am looking for suggestions on how to best approach this.
With an API you are just about to open a gate to process requests on your server without any session and browser. CSRF tokens are just validating form requests to make sure it's sent from your website. As far as I know it's absolutely ok to turn off CSRF protection for APIs.
You can use csrf_exempt decorator for this.
Read this article to learn more about CSRF and Web API protection.
I have an existing, working Django application that implements numerous Django-REST-framework APIs.
I've just added user authentication with Django-rest-framework-JWT and now I'm trying to learn it up. I have verified that it does issue me a token if I do the following curl:
curl -X POST -d "username=myuser&password=mypassword" http://localhost:3050/api-token-auth/
But I have a series of questions that I don't see being addressed in the documents. Please answer the following questions:
How do I invalidate the token using curl? I need to do so when the user logs out.
Where are these tokens stored in the DB? After implementing django-rest-framework-jwt, I don't see any new tables in my Django Admin interface
I would like to allow my users to login with their usernames or their emails. So I would like to wrap the api-token-auth endpoint in a custom endpoint that checks if the given string is an email or username. If email, I will lookup the username. Then call the api-token-auth. How should that endpoint look? I don't know how to wrap this api-token-auth method.
When using JWT for authentication you'd usually store the token in the browser's localstorage or sessionstorage. To logout you just remove the token. There's nothing else to invalidate.
One of the benefits of using this kind of approach for authentication is that tokens are not persisted in the database, so you don't have to query a session store for anything when authenticating.
This should be possible with a custom Django Authentication Backend as well.