Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django rest auth with Allauth

I have implemented django rest auth with Allauth and its working fine if I login through google access_token but there is a case when some client device need to login by google id_token. I am getting error if I use id_token instead of access_token

{
  "non_field_errors": [
    "Incorrect value"
  ]
}

please help me out

like image 529
Samanya Hind Avatar asked Feb 25 '17 09:02

Samanya Hind


People also ask

Is django-allauth good?

django-allauth is an integrated set of Django applications dealing with account authentication, registration, management, and third-party (social) account authentication. It is one of the most popular authentication modules due to its ability to handle both local and social logins.

How do I add social login to Django?

Django Setup Set up the initial tables and add a superuser: $ python manage.py migrate Operations to perform: Apply all migrations: admin, contenttypes, auth, sessions Running migrations: Applying contenttypes. 0001_initial... OK Applying auth. 0001_initial... OK Applying admin.

What is DJ rest Auth?

Dj-Rest-Auth: a free and open-source package used for handling authentication in Django REST APIs.


1 Answers

Update your files like

../allauth/socialaccount/providers/google/provider.py:

class GoogleProvider(OAuth2Provider):
    ....

    def extract_uid(self, data):
        try:
            return str(data['id'])
        except KeyError:
            return str(data['user_id'])

../allauth/socialaccount/providers/google/views.py:

class GoogleOAuth2Adapter(OAuth2Adapter):
    provider_id = GoogleProvider.id
    access_token_url = 'https://accounts.google.com/o/oauth2/token'
    authorize_url = 'https://accounts.google.com/o/oauth2/auth'
    profile_url = 'https://www.googleapis.com/oauth2/v1/userinfo'
    token_url = 'https://www.googleapis.com/oauth2/v1/tokeninfo'

    def complete_login(self, request, app, token, **kwargs):
        if 'rest-auth/google' in request.path:
            print('rest-auth api')
            # /api/rest-auth/google
            # but not for website login with google
            resp = requests.get(self.token_url,
                            params={'id_token': token.token,
                                    'alt': 'json'})
        else:
            print('else else rest-auth api')
            resp = requests.get(self.profile_url,
                            params={'access_token': token.token,
                                    'alt': 'json'})
        resp.raise_for_status()
        extra_data = resp.json()
        login = self.get_provider() \
            .sociallogin_from_response(request,
                                   extra_data)
        return login


oauth2_login = OAuth2LoginView.adapter_view(GoogleOAuth2Adapter)
oauth2_callback = OAuth2CallbackView.adapter_view(GoogleOAuth2Adapter)

For using id_token you will get only these fileds (access_type, audience, email, email_verified, expires_in, issued_at, issued_to, issuer, nonce, scope, user_id, verified_email). So if your user table required phone and name you can set the to empty name='' etc. For this you can use the following code.

Set user model required fields to empty for covering id_token case

It depends upon your user model, in my case we need both phone and name so I have set them empty. If you don't do this you will get failed constraints errors.

../allauth/socialaccount/providers/base.py

class Provider(object):
    def sociallogin_from_response(self, request, response):
        ....
        common_fields = self.extract_common_fields(response)
        common_fields['name'] = common_fields.get('name', '')
        common_fields['phone'] = common_fields.get('phone', '')
        common_fields['username'] = uid
        ....

I have set the username to user id obtained from social platform api. Later I am forcing user to update its details (username, name, phone etc).

like image 97
Umar Asghar Avatar answered Sep 20 '22 08:09

Umar Asghar