title: Google login in django rest framework + allauth + rest-auth
body: <p>I'm trying to implement <strong>Google authentication</strong> in django with <strong>allauth</strong> and <strong>rest-auth</strong>. After many hours of research, none of the solutions I found worked in my project.</p>
  
  <p>I based my code on a github issue: <a href="https://github.com/Tivix/django-rest-auth/issues/403" rel="noreferrer">https://github.com/Tivix/django-rest-auth/issues/403</a></p>
  
  <p>And an article:
  <a href="https://medium.com/@gonzafirewall/google-oauth2-and-django-rest-auth-92b0d8f70575" rel="noreferrer">https://medium.com/@gonzafirewall/google-oauth2-and-django-rest-auth-92b0d8f70575</a></p>
  
  <p>I have also created a <strong>Social Application</strong> object with Google <strong>client id</strong> and <strong>client secret</strong></p>
  
  <h2>My project setup in google console:</h2>
  
  <p>Authorized JavaScript origins: <strong><a href="http://localhost:8000" rel="noreferrer">http://localhost:8000</a></strong>
  Authorized redirect URIs: <strong><a href="http://localhost:8000/api/v1/users/login/google/callback/" rel="noreferrer">http://localhost:8000/api/v1/users/login/google/callback/</a></strong></p>
  
  <h2>My code</h2>
  
  <p><strong>providers.py</strong>:</p>
  
  <pre class="lang-py prettyprint-override"><code>from allauth.socialaccount.providers.google.provider import GoogleProvider
  
  
  class GoogleProviderMod(GoogleProvider):
      def extract_uid(self, data):
          return str(data['sub'])
  
  </code></pre>
  
  <p><strong>adapters.py</strong>:</p>
  
  <pre class="lang-py prettyprint-override"><code>from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter
  from google.auth.transport import requests
  from google.oauth2 import id_token
  
  from myproj.users.providers import GoogleProviderMod
  
  
  class GoogleOAuth2AdapterIdToken(GoogleOAuth2Adapter):
      provider_id = GoogleProviderMod.id
  
      def complete_login(self, request, app, token, **kwargs):
          idinfo = id_token.verify_oauth2_token(token.token, requests.Request(), app.client_id)
          if idinfo["iss"] not in ["accounts.google.com", "https://accounts.google.com"]:
              raise ValueError("Wrong issuer.")
          extra_data = idinfo
          login = self.get_provider().sociallogin_from_response(request, extra_data)
          return login
  </code></pre>
  
  <p><strong>views.py</strong>:</p>
  
  <pre class="lang-py prettyprint-override"><code>from allauth.socialaccount.providers.oauth2.client import OAuth2Client
  from rest_auth.registration.serializers import SocialLoginSerializer
  from rest_auth.registration.views import SocialLoginView
  
  from myproj.users.adapters import GoogleOAuth2AdapterIdToken
  
  
  class GoogleLoginView(SocialLoginView):
      adapter_class = GoogleOAuth2AdapterIdToken
      callback_url = "http://localhost:8000/api/v1/users/login/google/callback/"
      client_class = OAuth2Client
      serializer_class = SocialLoginSerializer
  </code></pre>
  
  <p><strong>urls.py</strong>:</p>
  
  <pre class="lang-py prettyprint-override"><code>from allauth.socialaccount.providers.oauth2.views import OAuth2CallbackView
  from django.urls import path
  
  from myproj.users.adapters import GoogleOAuth2AdapterIdToken
  from myproj.users.views import GoogleLoginView
  
  app_name = "users"
  urlpatterns = [
      path(
          "login/google/",
          GoogleLoginView.as_view(),
          name="google_login"
      ),
      path(
          "login/google/callback/",
          OAuth2CallbackView.adapter_view(GoogleOAuth2AdapterIdToken),
          name="google_callback"
      ),
  ]
  </code></pre>
  
  <p><strong>settings.py</strong>:</p>
  
  <pre class="lang-py prettyprint-override"><code>AUTHENTICATION_BACKENDS = [
      "django.contrib.auth.backends.ModelBackend",
      "allauth.account.auth_backends.AuthenticationBackend",
  ]
  ACCOUNT_DEFAULT_HTTP_PROTOCOL = "http"
  </code></pre>
  
  <p>When I passing <strong>ID Token</strong> (returned from Google 'sign in' button) as <strong>code</strong> parameter on login page, the error occurring:</p>
  
  <p><code>allauth.socialaccount.providers.oauth2.client.OAuth2Error: Error retrieving access token: b'{\n  "error": "invalid_grant",\n  "error_description": "Malformed auth code."\n}'</code>
  Response code is 400.</p>
  
  <p>Actually, even if I passing some random text to the <strong>code</strong>, the error is the same.</p>
  
  <p>Thanks for help!</p>