How to return the user object with django rest framework and allauth - django-rest-framework

I have Google sign in working in my Django api using Django rest framework and allauth. When a user authenticates the generated token is returned, which is great.
However I would like to have both the token and the new User data returned, is this possible? A structure similar to this:
{
token: TOKEN_VALUE
user: {
name: "xxx",
email: "xxx",
...ect.
}
I would imagine this would require a change to the view which currently looks like this:
class GoogleLogin(SocialLoginView):
adapter_class = GoogleOAuth2Adapter
client_class = OAuth2Client
Is there a way to change what is returned, or do I need to make a second call to get the user object?

Related

Django RF simplejwt returns only token, not user object

I have React app and a Redux store. I am working on an authentication now. My backend is on Django RF and for JWT auth I use a simplejwt lib. The thing is, that this lib has an "out of the box" view (/token) that returns a JWT token on success.
The problem is that I need to have a user object in my app upon successful authentication. So when the user logs in it returns a token only. But I need to redirect the user to their page if logged in.
I sure can override this /token view and return whatever object I want, but why is this implemented this way right now?
Looks like there is no other way that to override validate() method in serializers.py like this:
class UserTokenObtainPairSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
data = {
'token': super().validate(attrs),
'id': self.user.id,
'email': self.user.email,
'name': self.user.name,
}
return data

Getting user details from access token in Django rest framework -simple JWT

I am using React and Django rest framework for a project. I use Django rest framework simple JWT for authentication. Now, I want to display the username in the navbar after the user logs in. So, is there a way in simple JWT for returning user details from the access token generated after authentication, just like Djoser returns user credentials when supplied the access token?
Sorry if this question is silly but I was not able to find a solution to this anywhere.
if you want to obtain the information of the owner of the token you can consult it in REQUEST.
class ViewProtect(APIView):
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def post(self, request, format=None):
token_user_email = request.user.email
token_user_username = request.user.username
pass
About the backend, basically I use this library
from restframework_simplejwt.tokens import AccessToken
The function AccessToken() take as input the string access_token_str and return the object access_token_obj.
To get the user_id, you can use the instruction
user_id=access_token_obj['user_id'].
In the following example I have created the function
get_user_from_access_token_in_django_rest_framework_simplejwt().
This function is just a wrapper around AccessToken()
Full code:
#Path current file
#/blabla/django/project004/core/view.py
from restframework_simplejwt.tokens import AccessToken
from django.contrib.auth.models import User
#Example data.
#access_token_str = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiY29sZF9zdHVmZiI6IuKYgyIsImV4cCI6MTIzNDU2LCJqdGkiOiJmZDJmOWQ1ZTFhN2M0MmU4OTQ5MzVlMzYyYmNhOGJjYSJ9.NHlztMGER7UADHZJlxNG0WSi22a2KaYSfd1S-AuT7lU'
def get_user_from_access_token_in_django_rest_framework_simplejwt(access_token_str):
access_token_obj = AccessToken(access_token_str)
user_id=access_token_obj['user_id']
user=User.objects.get(id=user_id)
print('user_id: ', user_id )
print('user: ', user)
print('user.id: ', user.id )
content = {'user_id': user_id, 'user':user, 'user.id':user.id}
return Response(content)
Credits:
#davesque;
https://github.com/jazzband/djangorestframework-simplejwt/issues/140
Update.
The string access_token_str I write in the file is just an example. You should pass it as argument.
Here's how I've done it.
On Django, I followed the steps described on this page in order to add the user's name inside the JWT token : https://django-rest-framework-simplejwt.readthedocs.io/en/latest/customizing_token_claims.html
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
#classmethod
def get_token(cls, user):
token = super().get_token(user)
# Add name to token
token['name'] = user.get_full_name()
# You can add other information into the token here
return token
class MyTokenObtainPairView(TokenObtainPairView):
serializer_class = MyTokenObtainPairSerializer
Then, I updated my urls.py to use the custom view:
path('token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
Finally, in my Vue.js application, I installed the jwt-decode package and used it like this:
const token = localStorage.getItem('access_token');
const decoded = jwt_decode(token);
console.log(decoded)
// decoded.name contains the user's full name
Note that I store the access token in the local storage beforehand.

How can I test if the django rest form output contains some value?

The django rest framework forms related fields sometimes leak things I don't want. I want to write a test for it.
I tried this:
class CVRequestAPITests(APITestCase):
def test_disallow_read_access(self):
url = reverse('cvrequest-list')
response = self.client.get(url, headers={
'Accept': 'text/html,application/xhtml+xml'
})
But it still gives JSON.

"Method \"POST\" not allowed." Django REST

I am new to django rest framework. I have an api to get corresponding token for each user. The method defined to access token is
class ObtainAuthToken(APIView):
def post(self, request):
user = authenticate(
username=request.data['username'], password=request.data['password'])
if user:
token, created = Token.objects.get_or_create(user=user)
return Response({'token': token.key, 'user': UserSerializer(user).data})
return Response('Invalid username or password', status=status.HTTP_400_BAD_REQUEST)
and in urls.py i have
url(r'^login/$',ObtainAuthToken, name='login')
But while logging in a user, i am getting the response as
{
"detail": "Method \"POST\" not allowed."
}
Where did i went wrong?
First of all - I see that you used the django-rest-auth tag. Are you actually using rest auth? If not - you should definitely consider doing it as it provides a ton of auth functionality out of the box.
As to your question, you forgot to call as_view() on ObtainAuthToken in your url conf. Change it like so and tell me if it works:
url(r'^login/$', ObtainAuthToken.as_view(), name='login')
You have the wrong indentation in your code. The post method needs to be inside the ObtainAuthToken(APIView) class. Right now is defined as a standalone function.

Parse Cloud Code on Heroku User Query

I am trying to access properties located on the User object for the current user in a cloud code function. The current user is passed to the cloud code function and available at request.user. The Cloud Code is deployed to Heroku using parse-cloud-express.
When the request first arrives, it does not contain the user data other than the id.
So I tried performing a fetch to get the latest data:
Parse.Cloud.define("functionName", function (request, response) {
request.user.fetch().then(function (user) {
console.log(util.inspect(user));
});
});
But it outputs the same data and does not seem to include the User object's properties.
2015-12-15T01:19:08.830880+00:00 app[web.1]: { _objCount: 1, className: '_User', id: 'dKqZMSRgDc' }
I also tried performing a query on the user id, but receive the same result.
var userQuery = new Parse.Query(Parse.User);
userQuery.get(request.user.id).then(function (user) {
console.log(util.inspect(user));
});
How do I get the properties of the User object?
The problem was not with getting data for the User object, but the way I was logging it. It seems that the data is not available from the object itself, so the output from util.inspect was correct, but does not include any properties. (I'm guessing the internals of the Parse framework manages this in another way.)
I replaced with console.log(user.toJSON()) and can now see the expected data for the user.

Resources