I'm new learning graphene with django, and as the documentation says, I have this class:
import graphql_jwt
class Mutations(graphene.ObjectType):
token_auth = graphql_jwt.ObtainJSONWebToken.Field()
verify_token = graphql_jwt.Verify.Field()
refresh_token = graphql_jwt.Refresh.Field()
but calling the tockenAuth mutation, even when the token is correcty generates because the user and password are correct, I don't see anything saved in the session table:
Session.objects.all()
is always empty
I'm checking the session for login out any user. So, how can I generate the Session entry from the authToken mutation call and what's the correct/better way to login/logout users using graphql_jwt?
Regards
JWT is an alternative to sessions - it is another way to authenticate a request so you do not need sessions if you use JWT.
JWT also does not create any kind of information in database - you can just use cryptography to verify that the token is legitimate. To authenticate with JWT include JSONWebTokenBackend in your AUTHENTICATION_BACKENDS as described here.
Read more about jwt here.
Related
I have been given a task to authenticate admin login programmatically and logout as well.
I am able to to do login but on logged out when I check which user I am logging out it says AnonymousUser. How can I make sure I log out current user which is logged it.
I am using Django REST framework and testing it on Postman.
#api_view(["POST"])
def adminLogin(request):
if(request.method=="POST"):
username = request.data["username"]
password = request.data["password"]
authenticated_user = authenticate(request,username=username, password=password)
if authenticated_user != None:
if(authenticated_user.is_authenticated and authenticated_user.is_superuser):
login(request,authenticated_user)
return JsonResponse({"Message":"User is Authenticated. "})
else:
return JsonResponse({"message":"User is not authenticated. "})
else:
return JsonResponse({"Message":"Either User is not registered or password does not match"})
#api_view(["POST"])
def adminLogout(request):
print(request.user)
logout(request)
return JsonResponse({"message":"LoggedOut"})
Logging in/logging out with a REST API makes not much sense. The idea of logging in/logging out, at least how Django implements it, is by means of the session, so with a cookie that has the session id.
API clients like Postman usually do not work with cookies: each request is made more or less independent of the previous one. If you thus make the next request without a reference to the session, then the view will not link a user to that request. Clients like AJAX that runs on the browser of course can work with cookies, since these are embedded in the browser that manages cookies. You can work with cookies in postman as specified in this tutorial [learning postman], but this is usually not how an API is supposed to work.
This is why APIs usually work with a token, for example a JWT token. When authenticating, these are given a token that might be valid for a short amount of time, and subsequently it uses that token to make any other request that should be authorized.
As the Django REST framework documentation on TokenAuthentication [drf-doc] says, you can define views that create, and revoke tokens. The page also discusses session authentication that thus can be used for AJAX requests.
But likely you are thus using the wrong means to do proper authentication for your REST API, and you thus might want to work with a token like a JWT token instead.
Hi i'm playing with django and djangorestframework-simplejwt and wrote a simple app to register users. Now it seems from reading the documentation and searching online the only way of generating a token is by passing the username, and password to the url url(r'^api/token/$', TokenObtainPairView.as_view(), name='token_obtain_pair'). So it seems i have to create the user first and upon successfully creating the user then send the username, and password again to the url to generate a token. But i want to be able to create a token when the user is created and not have to resend the username and password after user is created. Is there an easier away to generate a jwt when registering a user.
Yes, You can do that with RefreshToken.
Here is how...
from rest_framework_simplejwt.tokens import RefreshToken
from django.utils.six import text_type
def somewhere_in_signup_view:
...
refresh = RefreshToken.for_user(user)
tokens = {
'refresh_token': text_type(refresh),
'access_token': text_type(refresh.access_token),
}
...
Using:
Django 1.11
Python 3.6
DRF with JWT in FE
I understand that the Django admin uses a session, and basic authentication.
What I did so far: Replaced the Django Admin authentication signin page with AWS-Cognito:
The user goes to domain/admin/*, redirected to signin in AWS
On successful signin the user is redirected to the redirect_uri, leads to a Django View
In the view I replace the code with tokens
I can't navigate to any Admin page - I am trying to redirect, but that doesn't work since I didn't login() the User
Stuck - I would like to associate the User with the fetched tokens and authenticate with every Admin page request, and when the user logs out delete the tokens
What to do next?
When I use JWT with the Front End application, every request.META has HTTP_AUTHORIZATION, and uses a suitable backend.
I know how to add backends, and potentially leverage the user.backend (I also use Cognito-JWT for other FE portions, so already wrote BE for that)
I need to find a way to replace the Django Admin sessions authentication with the fetched token
Thank you!
EDIT:
If I login() the user, and set it to a model backend that I have already I can navigate to any admin page - but using the session that I created when I logged the user in.
I would like to have the user be set to a new model backend, with authentication that uses a token (from Django backend docs):
class MyBackend:
def authenticate(self, request, token=None):
# Check the token and return a user.
...
How do I make the different Admin pages requests pass the token to the authentication?
Where do I store the token? (I could make a NewUserModel that is 1-1 with the Django User model, and place a token field there)
I am thinking of writing a middleware to capture all requests, and looking into the target URL - if Admin url, add the token to the HTTP_AUTHORIZATION once I fetch the user mentioned in #2 (the user is in every request due to DRF)
EDIT 2
My solution is getting more and more like this stack solution, I would have liked to know if there are any other options, but here is what I did so far:
I made a model that has a 1-1 user field, and a tokens field
As I am fetching/creating the user, I am also saving the tokens on the user's related model from #1 above
I created a middleware that is capturing any request in process_request, and has access to the user. I can see the tokens there as I access the user's related model from #1 above.
I am trying to set the HTTP_AUTHORIZATION header on the request, but cannot do that yet (currently stuck here)
In my backend, I am looking at the incoming request, and trying to fetch the HTTP_AUTHORIZATION - not there yet.
EDIT 3
I ended up just using the Django session as is - once the user authenticates with AWS-Cognito once, it is safe to assume that it is a legitimate User.
Then I just dump the Cognito-JWT, and login() the User.
Note: I am still interested in a solution that would drop the Django session for using the Cognito-JWT, and would love to hear suggestions.
I'm not sure I'm right on track. Please give me a hint or direction.
I set up my Web service using Django and also made mobile app with React Native using Django REST framwork. Django uses the basic session authentication, but Django REST API uses token authentication to process the request from mobile app.
I want to implement small ReactJS app into my existing Django web. At this stage, I think my small react app will need auth token to communicate with REST api for itself.
So, my idea is that when user logs in web login page, user's API token needs to be received from API and save into cookie or localStorage while normal log in process is processing in Django Web service. Because I don't want to let users log in again to run react app on my web page to get auth token.
Am I right on track? if so, how can I make it works? Please refer to my code in Django login view.py Do i need to some code in order to get API auth token and save it into client side?
def Login(request):
if not request.user.is_authenticated:
if request.method == "POST":
email = request.POST['email']
password = request.POST['password']
user = authenticate(email = email, password = password)
if user is not None:
login(request, user)
messages.add_message(request, messages.SUCCESS, request.user.nickname + ' Welcome!')
return redirect('Search')
else:
messages.add_message(request, messages.WARNING, 'Please check Email / Password again')
return redirect('login')
else:
form = LoginForm()
return render(request, 'login.html', {'form': form })
else:
return redirect('main')
You have done some useless in your login function. you can use jwt. it has some good function for supporting login. In its login function, when send username and password with post, it return token to client.
http://getblimp.github.io/django-rest-framework-jwt/
You just need set urlpattern
from rest_framework_jwt.views import obtain_jwt_token
#...
urlpatterns = [
'',
# ...
url(r'^api-token-auth/', obtain_jwt_token),
]
It return token
$ curl -X POST -d "username=admin&password=password123" http://localhost:8000/api-token-auth/
In other request, if you need authentication, use following request
$ curl -H "Authorization: JWT <your_token>" http://localhost:8000/protected-url/
They both carrying out similar tasks with few differences.
Token
DRF's builtin Token Authentication
One Token for all sessions
No time stamp on the token
DRF JWT Token Authentication
One Token per session
Expiry timestamp on each token
Database access
DRF's builtin Token Authentication
Database access to fetch the user associated with the token
Verify user's status
Authenticate the user
DRF JWT Token Authentication
Decode token (get payload)
Verify token timestamp (expiry)
Database access to fetch user associated with the id in the payload
Verify user's status
Authenticate the user
Pros
DRF's builtin Token Authentication
Allows forced-logout by replacing the token in the database (ex: password change)
DRF JWT Token Authentication
Token with an expiration time
No database hit unless the token is valid
Cons
DRF's builtin Token Authentication
Database hit on all requests
Single token for all sessions
DRF JWT Token Authentication
Unable to recall the token without tracking it in the database
Once the token is issued, anyone with the token can make requests
Specs are open to interpretations, no consensus on how to do refresh
Reference: Django : DRF Token based Authentication VS JSON Web Token
I'd like to leave my answer after I solved in my way through my long research and study. My solution is quite simple.1. set DRF session authentication enable. Adding some code in setting.py
REST_FRAMEWORK = {
# ...
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
}
2. add 'credentials: "include"' into fetch code to use already logged in session cookie for authentication.
await fetch(API_URL, {
credentials: "include"
})
this solution solved my case.
Is it possible to use Django JWT rest framework to create a password recovery link?
An example would be to recover password by email and create an access token for it.
Or do I need to use the features of Django admin to do this?
Thank you very much.
This is not something you can do in Django JWT REST framework alone. You need to write custom views to fulfil this behavior.
You can subclass auth.PasswordResetView and create a new JWT token manually that is used in a password reset link delivered to email address of active user.
The following example is given in django-rest-framework-jwt for creating JWT token manually.
# Source: https://jpadilla.github.io/django-rest-framework-jwt/#creating-a-new-token-manually
from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
You'll also need to subclass auth.PasswordResetConfirmView to verify that the token wasn't used/expired.
Another option is to use Djoser.
This library would allow you to configure a password reset endpoint, user creation, password change, configure the email, etc. It is also compatible with JWT.