My Django application uses the Rest Framework JWT for authentication. It works great and very elegant.
However, I have a use-case which I am struggling to build. I have already coded up a working solution for the "Forgot Password" workflow. I allow an un-authenticated user to reset their password if-and-only-if they click on a secret link that I send to their email address. However, I would like to modify this solution such that after the password-reset workflow is successfully completed, the user is automatically logged in without having to retype their username and (new) password. I would like to do this to make the user's experience as frictionless as possible.
The problem is I do not know how to make this work without having the user re-type their password (or storing it in clear-text in the DB which is obviously very bad). Below is the current way I get the JWT token. You can see that in line #12, I need the user's clear password. I don't have it. I only have the encrypted password stored in my_user.password
.
How can I use the encrypted password in my_user.password instead of the clear password to obtain the JWT? If I cannot use it, then how is this workflow achieved using the Rest Framework JWT?
from rest_framework_jwt.views import ObtainJSONWebToken
from rest_framework status
from django.contrib.auth.models import User
my_user = User.objects.get(pk=1)
ojwt = ObtainJSONWebToken()
if "_mutable" in dir(request.DATA):
mutable = request.DATA._mutable
request.DATA._mutable = True
request.DATA['username'] = my_user.username
request.DATA['password'] = "<my_user's clear password>"
if "_mutable" in dir(request.DATA):
request.DATA._mutable = mutable
token_response = ojwt.post(request)
if status.is_success(token_response.status_code):
# Tell the user login succeeded!!
else:
# Tell the user login failed.
# But hopefully, this shouldn't happen
When working with Django REST Framework JWT, it is typically expected that the user is generating the token on their own. Because you are generating the token on behalf of the user, you can't use any of the standard views to make it work.
You are going to need to generate the token on your own, similar to how DRF JWT does it in the views. This means using something like the following for your view code
from rest_framework_jwt.settings import api_settings
from datetime import datetime
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
my_user = User.objects.get(pk=1) # replace with your existing logic
payload = jwt_payload_handler(my_user)
# Include original issued at time for a brand new token,
# to allow token refresh
if api_settings.JWT_ALLOW_REFRESH:
payload['orig_iat'] = timegm(
datetime.utcnow().utctimetuple()
)
return {
'token': jwt_encode_handler(payload)
}
This should allow you to manually generate the token within the view, without having to know the user's password.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With