I'm new-ish to Django and Token based authentication and have both a multi page site from django (non-DRF) with standard allauth session-based authentication, and a react app using graphQL on DRF and JWT authentication. They are on different subdomains but use the same django/db instance.
I would like my users to be able to log in on either site and navigate to the other and still stay 'authenticated'. i.e. not have to log in again.
I was thinking about trying to get my non-DRF site to use JWT, but there doesnt seem to be much online content on this that isnt DRF. Also is it even possible to provide a token cross subdomain?
Is this all a pipe dream? Can someone please point me in the best direction to solve this problem?
Thanks in advance for your time.
Simply use SessionAuthentication on Rest API Default Authentication classes
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
.........
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework_simplejwt.authentication.JWTAuthentication',
..........
]
}
This will ensure you are using session Authentication which shares the session cookie along all sites for authentication with which you can use both JWT and Session authentication. But be careful because your api can also be accessed with Session Authentication.
This is not a backend issue, simply local storage or any type of Browser storage does not allow one site/domain to access the data of another. I would suggest using the DRF for all the functionality and dropping the non-DRF one, but you can append the user JWT token to the link when redirecting the user from the drf site to the non-drf site and then extract the token and set it as an auth header. please explain why you need two separate backend apps, ill recommend if their is a better way.
Related
In my django web app, which is split into a front and and a back end project, I am currently using a custom AuthBackend class that extends django's BaseBackend, as well as DRF's UserTokenAuthentication.
Am I right to think that I only need one of these approaches? Or is there a reason to use django's login() function, even if i am using DRF's token auth? I know it stores the user in the session, so I guess that would make passing and authenticating a token pointless?
What's my best approach? Cheers :)
There are differences in both namespaces wise and purpose wise.
In Django, auth backends handle session-based authentication only whereas rest framework auth supports not only session-based auth but also token (JWT, OAuth ), and basic auth based authentication.
Besides, Django auth backends authenticate requests during passing through middle-ware and rest framework authenticate without middle-ware.
If you are planning to separate your backend and frontend then go for token-based auth. There is no reason to use the login function of Django if you only use token-based auth to authenticate.
I am building an application after finishing up my website. Now, the backend for both of these should be common, but Django's csrf token is meant to be a security against this. Since I am not using a web browser, I am unable to get a csrf token cookie. At the same time, django will need it to access its APIs.
Is there any way I can get the cookie from Django and get it into React Native?
Not clear what you want to do. But if you are writing a native application, why don't you use a token identification mechanism?
There are lots of simple (and less simple solutions out there).
Assuming you are using django rest framework.
Simple built-in Token authentication
https://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication
Token, but with expiry and DB encryption
https://github.com/James1345/django-rest-knox
JWT
https://github.com/davesque/django-rest-framework-simplejwt
May I know your login URL? Use rest-auth login URL. Allauth URL gives Csrf issue.
Setup
An angular application (~1.5) and django with django (1.9.9) rest framework (3.5.3) running on a server with nginx serving the client directly as static files from / and the api through uwsgi from /api
djangorestframework-jwt is in use to provide and validate the JWT tokens for the client.
Reproducing the error:
User logs into the client front end (angular app) successfully.
User clicks a link and GETs some data from the api.
User clicks to edit the data and changes form data and PUTs it to the api
All is well
User gots to /api and logs in via the DRF browsable API with same username and password
Goes back to / and tries to submit a form with PUT again.
Angular forwards the following error from the django server.
{"data":{"detail":"CSRF Failed: CSRF token missing or incorrect."},"status":403, JWT..., "statusText":"Forbidden"}
Finding the cause
Trying to narrow down the issue, I find that there is no csrf cookie nor session cookie found after logging in with the client app. I'm using JWT for authentication, so it shouldn't need any session.
The JWT token is being saved to local storage, not cookies.
After logging into the /api or /administration applications which are handled by django without angular at all, a csrftoken cookie and session cookie are set for that domain.
If I delete the csrf cookie, the angular app still can't PUT or POST. But if I delete the session cookie, it starts to work properly again.
Question
How should I be setting up the Django and/or Angular apps so that the user can login to either one without causing conflict?
Things I've considered
If users don't login to the backend app at all, there is no problem for them. But some will need to occasionally.
If I cause the session cookie to be deleted by Angular, the user will be logged out of the Django app, causing frustration if they need to have both open.
Solution
In working on clarifying this well enough to write a SO post, I've found a solution. Essentially, change Django settings to authenticate against the JWT first, so it never tries to check the session.
See below for more detail.
Since Django tends to process settings in the order they are listed, I tried moving the JSONWebTokenAuthentication line to the top of the list instead of the bottom as it would normally be when following the example on the REST framework JWT Auth docs page.
This worked out. So instead of throwing away the question I was almost done with, I've posted it here for your reading enjoyment.
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
A misleading feature of this error is that the csrf token didn't seem to be the actual problem. It was the session token that angular was passing back because angular was being served from the same host as the API.
I am currently working on a Django project that wants to replace and disable Django's traditional cookie-based sessions and replace it with JSON web tokens as a means of user authentication for a user on my website.(User Authentication for the 'login-required' part of the website instead of just REST API's).
How I want JSON web tokens to be used in my web app: The login page will make an API call and receive a JSON web token as a response and the JSON web token will be stored through (local storage, session storage, or cookies). The JSON web token will be passed in the HTTP header in subsequent HTTP requests (after logging in) so that the server knows we are an authorized user.
Some of the libraries that I have looked at is the 'djangorestframework' library. It seems to protect certain URLS concerning a site's API (not what I want). Are there any libraries that can replace the normal 'cookie-based' sessions Django uses with JSON web tokens and have the normal functionality of 'cookie-based' session authorization scheme(Normal meaning 'logging a user in and logging a user out works on the site as well as in the Django's default admin panel') If so, how do I integrate that library with my current web app to achieve normal functionality?
I also want the traditional 'cookie-based' sessions to be disabled. How do I completely disable it so user authentication is done only with JSON web tokens?
Simply use jwt to authentication class.
JSON Web Token Authentication
JSON Web Token is a fairly new standard which can be used for token-based authentication. Unlike the built-in TokenAuthentication scheme, JWT Authentication doesn't need to use a database to validate a token. Blimp maintains the djangorestframework-jwt package which provides a JWT Authentication class as well as a mechanism for clients to obtain a JWT given the username and password
Also set default authentication class to jwt and determine setting in setting.py like :
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
)
}
i'm currently learning about django-rest and i'd like to interact with an Angularjs application.
The main idea is to build an API with django-rest serving on localhost:8000 and call it with a nodejs/angularjs serving on localhost:9000
the main question is: how to authenticate an user through angularjs ?
The documentation says
Session authentication is appropriate for AJAX clients that are
running in the same session context as your website.
because django and angularjs are not in the same context, does it means i have to use oauth2 to play with authentication ?
Thanks for your lights :)
does it means i have to use oauth2 to play with authentication?
Of course not. You can use TokenAuthentication or even BasicAuthentication.
I myself most of the times use something similar to TokenAuthentication but handmade. The only concern here is passing token in requests.
EDIT:
If you perchance not satisfied with options provided by Django REST you can write your own middleware to handle authentication. The idea here is to authenticate user. Pass to him some token and then check for that token in your custom middleware.