How to get user details using JWT token - django

I'm using angular 5 front end and django as back end. I use JWT token to communicate between django to angular. How can I get logged user details in backend using token.
EG:
class PostSerializer(ModelSerializer):
class Meta:
model = PostDetail
fields = [
'title',
'upvote',
]
Here upvote is a many to many field contain all voted user list. I want to add one more field "user_vote_status" to check the vote status of logged in user.
How can I figure out this issue, please help me.

Here it is. JWT is made of three parts divided by "." The center part contains the user details. So you get that with split and decode that part with window.atob
function getUserInfo() {
const token = getToken();
let payload;
if (token) {
payload = token.split(".")[1];
payload = window.atob(payload);
return JSON.parse(payload);
} else {
return null;
}
}
function getToken() {
return localStorage.getItem("jwt-token");
}

You can get usernamec in any django view by this way
#api_view(['POST'])
def apiname(request):
username = request.user.username
as from angular front end, you need to send jwt token in headers
Authorization: JWT "token"

Related

getting the current user with Django drf and simple jwt

I was trying to get the current user with rest framework and simple jwt
I'm new to Django and I wrote a simple view that does(ish) the job
class UserDetail(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
authentication_classes = [JWTAuthentication,]
permission_classes = [IsAuthenticated,]
but for some reason when I post the user credentials to the endpoint in postman it says
{
"detail": "Authentication credentials were not provided."
}
but when I remove the ==> authentication_classes = [JWTAuthentication,] and
permission_classes = [IsAuthenticated,]
it works and gite the current user, my question is is this the right way of doing it, and are there any risks in doing it this way and if their is a better and more secure way of doing it. thanks in advance!!
this is the screenshot of the postM request data
and this is the URL for the class:-
path('detail/', UserDetail.as_view({'get':'list'}), name="blacklist"),
You have to pass the access token in the request.
If you are not confident in setting up simplejwt, follow this guide:
If you use postman to test the API, you can provide Authorization details like shown in this image
If you are using any other medium to send requests, then you can add Authorization in the request's header: {"Authorization": "Bearer <access_token>"}
if you are able to generate the token. All you have to do is pass the token in Postman url localhost:8000/detail/ and under the Authorization tab, select the Bearer token and paste the token which has been generated and send it. Under settings.py edit Simple JWT settings by adding Bearer after JWT in AUTH_HEADER_TYPES. Hope this works for you.

Retrieving users password from Django and passing as variable to log in to Django REST

I have a Django powered web-app which also utilizes the Django REST framework. I want to read and write to my database using the API generated by Django REST.
I can do this successfully when I hardcode the password of the current user, but I can't do this when I attempt to pass in the retrieved password from Django, as Django does not store the password as plain text. (I know I can change this, but I am hoping there is a better way).
Essentially, my logic flow is this:
user logs in using Django login form
user would like to write new data to database, but will need API token
Obtain API token (already generated when they sign up)
use this token to authenticate and POST JSON data to REST framework
I can do all of these steps above when I hardcode the password as plain text in my script, but I would like to "retrieve" the password and pass it automatically if possible.
Code below works as described above:
views.py
class DefaultsListView(LoginRequiredMixin,ListView):
model = models.DefaultDMLSProcessParams
template_name = 'defaults_list.html'
login_url = 'login'
def get_queryset(self):
return models.DefaultDMLSProcessParams.objects.filter
(customerTag=self.request.user.customerTag)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
testing = super().get_context_data(**kwargs)
userName = str(self.request.user.username)
passWord = str(self.request.user.password)
url = 'http://127.0.0.1:8000/api-token-auth/'
context = {'tokenURL': url, 'user':userName, 'pass':passWord}
return context
template.html
<div class = "debugging">
<p id = "csrf">{% csrf_token %}</p>
<p id = "tokenURL">{{tokenURL}}</p>
<p id = "user">{{user}}</p>
<p id = "pass">{{pass}}</p>
</div>
script.js
var csrfToken = document.querySelector("#csrf input").value;
var user = document.getElementById("user").innerHTML;
var pass = document.getElementById("pass").innerHTML;
var xhr = new XMLHttpRequest();
var url = "http://127.0.0.1:8000/api-token-auth/";
xhr.open("POST", url,);
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader( "X-CSRFToken", csrfToken);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var json = JSON.parse(xhr.responseText);
console.log(json.token);
}
};
var data = JSON.stringify({"username": user, "password": 'myhardcodedpass' });
xhr.send(data);
This script will log the API token of the current user to the console as expected. But instead of hardcoding the password, I would like to just pass it as a variable, but the password is a very long string as it is not stored as plain text (var pass). So trying to use pass is rejected, as it obviously isn't the correct password when passed as text.
Is there a way to decrypt this password, or translate it somehow? Or perhaps an easier way to retrieve the API token from Django REST?
First and foremost, you should definitely NOT store the password as plain text. That is never the solution in any case, and only will cause problems.
I have a few suggestions that you can potentially use, but the easiest would be to simply use a JSON Web Token which can easily be integrated with Django Rest Framework using the django-rest-framework-jwt library.
Your workflow would basically be as follows:
User logs in successfully, which returns a JWT to authenticate the user
The script would be included in the header of the request, and the middleware would be able to successfully identify and authenticate the user.
Hopefully this gives you an idea on how to move forward. Best of luck

Getting django rest framework jwt authentication to work [django rest, angular 5]

so I have installed djanogo rest framework JWT and set the settings and authetication classes. According to this guide. I will leave out the settings as they are correct, and that is not where the problem lies. It is also to not post too much code
https://jpadilla.github.io/django-rest-framework-jwt/
I then make a call to a authorization view on my server from the front end
let token = "hardcoded token just to get the service working";
if(token != null){
this.authservice.authorizetoken(token)
.subscribe(
(req: any)=>{
console.log(req);
}
);
// grab the permissions a user has and who they are by token
authorizetoken(token){
return this.http.get(userauthorization, {
headers: new HttpHeaders().set('Authorization', 'JWT' + token )
});
}
then in my django here is the view code:
class UserAuthorization(APIView):
authentication_classes = (JSONWebTokenAuthentication,)
def get(self, request, *args, **kwargs):
print(request.user)
return Response({})
but I keep getting anonymousUser returned. Shouldn't it be a user object since I am passing a token in the header?
I dont know what I am doing wrong.
According to documentation the headers should be in format Authorization: JWT <your_token>. When you are setting the token in headers inside your authorizetoken function, you are missing a white-space between 'JWT'+ token. This might be the problem for not authenticating the user. Have you tried the endpoint with Postman?

Validate and get the user using the jwt token inside a view or consumer

I am using django-rest-framework for the REST API. Also, for JSON web token authentication I am using django-rest-framework-jwt. After a successful login, the user is provided with a token. I have found how to verify a token with the api call, but is there any way to validate the token inside a view and get the user of that token, similar to request.user?
I need it to validate inside the consumer when using django-channels:
def ws_connect(message):
params = parse_qs(message.content["query_string"])
if b"token" in params:
token = params[b"token"][0]
# validate the token and get the user object
# create an object with that user
I was about to validate the token and get the user by importing VerifyJSONWebTokenSerializer class.
from rest_framework_jwt.serializers import VerifyJSONWebTokenSerializer
data = {'token': token}
valid_data = VerifyJSONWebTokenSerializer().validate(data)
user = valid_data['user']
Hope this helps any body like me.
Use TokenBackend instead of VerifyJSONWebTokenSerializer
from rest_framework_simplejwt.backends import TokenBackend
token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
data = {'token': token}
try:
valid_data = TokenBackend(algorithm='HS256').decode(token,verify=False)
user = valid_data['user']
request.user = user
except ValidationError as v:
print("validation error", v)

How to get a valid csrf token when using tastypie?

I am using tastypie to create an api for my Django project. My project requires that the user logins in order to make edits to models view etc. So my first step was to login the user using tastypie by creating the login and logout functions in the UserResource as described here. The response contained a sessionid cookie that i used to logout. My resources use SessionAuthentication and DjangoAuthorization. But when i try to post or put or delete on a model using a tastypie resource url, I get an error a 401 error. Some people suggested that i must use a valid csrf_token. But how can i do that when tastypie login view won't return one.
example code:
class EntryResource(ModelResource):
customer = fields.ForeignKey(CustomerResourse, 'customer', full=True)
creator = fields.ForeignKey(UserResource,'creator',null=True,full=True,blank=True)
class Meta:
queryset = Entry.objects.all()
resource_name = 'entry'
authorization = DjangoAuthorization()
authentication = SessionAuthentication()
my client.py
headers={"Content-Type":"application/json"}
#login. I don't get a csrftoken here, but works fine which is odd because i post data r
resp = requests.post(login_url, data=json.dumps(credentials), headers=headers)
cookies ={'sessionid':resp.cookies['sessionid']}
entry = {
'title':'New Entry',
'snippet':'New Snippet',
'created': datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S'),
}
entry_json = json.dumps(entry)
entry_add_response = requests.post(entry_api_url,data=entry_json,
headers=headers,cookies=cookies)
#entry_add_response.status_code is 401
#logout works as it should
logout_resp = requests.get(logout_url, cookies=cookies)
what am i doing wrong? Am I not doing the right steps?
all my urls have ?format=json appended to them. Tried without didn't work. I also tried changing from django and session authentication and authorization to basic (Authentication(), Authorization() ). I then get a 500 error. I starting to feel a bit desperate....