Open duplxey opened 1 year ago
I had this same problem and came to the similar conclusion. In my case I overrode GoogleOAuth2Adapter and changed response["id_token"]
to response["id_token"]["id_token"]
which fixed it.
Yeah, I only passed access_token to dj_rest_auth endpoint and it worked, as there was nothing as id_token returned from the Google client library..
On Mon, 24 Apr 2023, 16:54 Nik Tomazic, @.***> wrote:
I'm using dj-rest-auth on the backend and NextAuth.js https://next-auth.js.org/ on the frontend. After successfully logging in via NextAuth.js I get the following account passed to my signIn callback:
{ provider: "google", type: "oauth", providerAccountId: "177780422328299215542", access_token: "%access_token%", expires_at: 1682337884, refresh_token: "%refresh_token%", scope: "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile openid", token_type: "Bearer", id_token: "%id_token%" }
- access_token is a random string of characters. Not decodable by jwt.io.
- id_token is a JWT token (header.payload.signature). It is decodable by jwt.io.
I then forward the access_token and id_token to my dj-rest-auth Google endpoint defined like this:
from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapterfrom allauth.socialaccount.providers.oauth2.client import OAuth2Client, OAuth2Errorfrom dj_rest_auth.registration.views import SocialLoginView
class GoogleLogin(SocialLoginView): # Authorization Code grant adapter_class = GoogleOAuth2Adapter callback_url = "http://localhost:3000/api/auth/callback/google" client_class = OAuth2Client
I use the following request code:
const options = { method: 'POST', url: 'http://127.0.0.1:8000/api/auth/google/', headers: { 'Content-Type': 'application/json' }, data: { access_token: '%access_token%', id_token: '%id_token%' }}; axios.request(options).then(function (response) { console.log(response.data);}).catch(function (error) { console.error(error);});
This request fails with an error saying:
Not enough segments Internal Server Error: /api/auth/google/ Traceback (most recent call last): File ".\venv\lib\site-packages\jwt\api_jws.py", line 251, in _load header_segment, payload_segment = signing_input.split(b".", 1) ValueError: not enough values to unpack (expected 2, got 1)
The above exception was the direct cause of the following exception:
Traceback (most recent call last): File ".\authentication\views.py", line 33, in complete_login identity_data = jwt.decode( File ".\venv\lib\site-packages\jwt\api_jwt.py", line 168, in decode decoded = self.decode_complete( File ".\venv\lib\site-packages\jwt\api_jwt.py", line 120, in decode_complete decoded = api_jws.decode_complete( File ".\venv\lib\site-packages\jwt\api_jws.py", line 191, in decode_complete payload, signing_input, header, signature = self._load(jwt) File ".\venv\lib\site-packages\jwt\api_jws.py", line 253, in _load raise DecodeError("Not enough segments") from err jwt.exceptions.DecodeError: Not enough segments
The above exception was the direct cause of the following exception:
Traceback (most recent call last): File ".\venv\lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) File ".\venv\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, callback_kwargs) File ".\venv\lib\site-packages\django\views\decorators\csrf.py", line 56, in wrapper_view return view_func(*args, *kwargs) File ".\venv\lib\site-packages\django\views\generic\base.py", line 104, in view return self.dispatch(request, args, kwargs) File ".\venv\lib\site-packages\django\utils\decorators.py", line 46, in _wrapper return bound_method(*args, kwargs) File ".\venv\lib\site-packages\django\views\decorators\debug.py", line 92, in sensitive_post_parameters_wrapper return view(request, *args, *kwargs) File ".\venv\lib\site-packages\dj_rest_auth\views.py", line 48, in dispatch return super().dispatch(args, kwargs) File ".\venv\lib\site-packages\rest_framework\views.py", line 509, in dispatch response = self.handle_exception(exc) File ".\venv\lib\site-packages\rest_framework\views.py", line 469, in handle_exception self.raise_uncaught_exception(exc) File ".\venv\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception raise exc File ".\venv\lib\site-packages\rest_framework\views.py", line 506, in dispatch response = handler(request, *args, **kwargs) File ".\venv\lib\site-packages\dj_rest_auth\views.py", line 125, in post self.serializer.is_valid(raise_exception=True) File ".\venv\lib\site-packages\rest_framework\serializers.py", line 227, in is_valid self._validated_data = self.run_validation(self.initial_data) File ".\venv\lib\site-packages\rest_framework\serializers.py", line 429, in run_validation value = self.validate(value) File ".\venv\lib\site-packages\dj_rest_auth\registration\serializers.py", line 151, in validate login = self.get_social_login(adapter, app, social_token, response={'id_token': token}) File ".\venv\lib\site-packages\dj_rest_auth\registration\serializers.py", line 60, in get_social_login social_login = adapter.complete_login(request, app, token, response=response) File ".\authentication\views.py", line 46, in complete_login raise OAuth2Error("Invalid id_token") from e allauth.socialaccount.providers.oauth2.client.OAuth2Error: Invalid id_token
After some testing I figured out that response["id_token"] in complete_login returns the request's access_token and not the id_token.
print(response["id_token"])# prints out {'id_token': '%access_token%'}
Sending your id_token as the access_token without providing id_token seems to work:
const options = { method: 'POST', url: 'http://127.0.0.1:8000/api/auth/google/', headers: { 'Content-Type': 'application/json' }, data: { access_token: '%id_token%' }}; axios.request(options).then(function (response) { console.log(response.data);}).catch(function (error) { console.error(error);});
Is this the expected behaviour? Am I missing something?
— Reply to this email directly, view it on GitHub https://github.com/iMerica/dj-rest-auth/issues/503, or unsubscribe https://github.com/notifications/unsubscribe-auth/ASMTYPFSD6SPWZ4HZRZX2Y3XCZSXPANCNFSM6AAAAAAXJO35P4 . You are receiving this because you are subscribed to this thread.Message ID: @.***>
I'm very resistant to passing id_token to access_token, but it works anyway. Furthermore, in my case, I am also currently getting an error in the response where the refresh_token is returned as "".
@agent-Y do you have JWT_AUTH_HTTPONLY=False
defined in your settings? Per the docs, if JWT_AUTH_HTTPONLY=True
(default) the refresh token won't be sent. Initially I wanted to keep it true and just shuttle the JWT cookie back and fourth, but I wasn't able to get that working so I moved to sending the tokens in the body and saving them in local storage.
@cplanck Actually I'm using dj-rest-auth with djangorestframework-simplejwt (https://django-rest-framework-simplejwt.readthedocs.io/en/latest/getting_started.html# ), so I guess it is not dj-rest-auth's fault. But I'm looking for someone who is in the same situation.
This error only occurs with dj-rest-auth version 3.0.0. I fixed downgraded to2.2.8.
This error only occurs with dj-rest-auth version 3.0.0. I fixed downgraded to2.2.8.
I suppose this response is referring to the JWT problem, correct @agent-Y? I tried it with 2.2.8 and I still get Invalid id_token
if I don't pass my id_token
as the access_token
.
Yeah, I only passed access_token to dj_rest_auth endpoint and it worked, as there was nothing as id_token returned from the Google client library..
Interesting @iamrizwan077, I tried passing the id_token
and access_token
from the official Google OAuth 2.0 Playground and it didn't seem to fix anything. They were both included in the response though.
If it helps anyone, I recently abandoned this whole login flow and instead started using the Google Identity API with one-tap sign-on. It's a better user experience and is way easier to implement because it removes the complicated Oauth, redirect, code
, redirect flow that we're using here. Instead, the user logs in with Google and you get a JWT with the user info right in the browser. You then post request this to your backend to create an account, fetch your own JWTs, etc.
It feels like the way this "should" be done. The only downside I can see is that it removes Django allauth from the whole process, so if you need to support multiple social providers (Google, Facebook, etc.) it might make things more complicated. On the flip side, if you just need Google you can skip all the allauth overhead, extra tables, etc., and instead register users/retrieve details using your standard workflow.
More details here: https://developers.google.com/identity/gsi/web/guides/overview
Yeah, I only passed access_token to dj_rest_auth endpoint and it worked, as there was nothing as id_token returned from the Google client library..
Interesting @iamrizwan077, I tried passing the
id_token
andaccess_token
from the official Google OAuth 2.0 Playground and it didn't seem to fix anything. They were both included in the response though.
@duplxey Here is the relevant frontend code that I used:
import { GoogleLogin, GoogleOAuthProvider } from '@react-oauth/google';
const Login = () => {
const responseGoogle = (response) => {
// Send the response (code or token) to your Django backend to authenticate the user
axios('https://iamrizwan066.pythonanywhere.com/dj-rest-auth/google/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: JSON.stringify({
access_token: response.credential,
}),
})
.then((res) => {
if (res.status === 200) {
navigate('/')
}
//Sending credential(Access token) part to django for token
responseToken(jwt_decode(response.credential));
})
}
return (
<div>
...
{/* Google Sign In button */}
<GoogleOAuthProvider clientId={`${googleClientId}`}>
<GoogleLogin
onSuccess={(credentialResponse) => {
responseGoogle(credentialResponse)
}}
onError={() => {
console.log('Login Failed');
toast("Login failed!")
}}
/>
</GoogleOAuthProvider>
...
</div>
);
}
The given Google Client library returns me a credential (jwt access token), client_id and select_by attribute. I send that credential to dj-rest-auth endpoint with key 'access_token' and it works. If I send any other key, I get error in console 'access_token expected'.. And have this in my backend:
class GoogleLogin(SocialLoginView):
adapter_class = GoogleOAuth2Adapter
callback_url = 'https://picspacevault.netlify.app' //my website frontend url
client_class = OAuth2Client
Since I am using Django Tokens for auth, so I am sending a further request to my custom URL for retrieving Django token from database based on user data sent through that credential..
This error only occurs with dj-rest-auth version 3.0.0. I fixed downgraded to2.2.8.
I suppose this response is referring to the JWT problem, correct @agent-Y? I tried it with 2.2.8 and I still get
Invalid id_token
if I don't pass myid_token
as theaccess_token
.
Sorry. My explanation is inadequate. refresh_token was meant to be a downgrade response to an error that returned with "". Sorry for the confusion.
I had the same problem then I switched to dj-rest-auth[with_social]==2.2.5
and It just worked fine.
I had the same problem, and I solved it by fixing the following dependency:
django-allauth==0.50.0
This solution works with dj-rest-auth==4.0.1
I had the same problem, and I solved it by fixing the following dependency:
django-allauth==0.50.0
This solution works with dj-rest-auth==4.0.1
Downgrading to 0.50.0 worked for me, hoping this is fixed soon in newer releases
I had the same problem, and I solved it by fixing the following dependency:
django-allauth==0.50.0
This solution works with dj-rest-auth==4.0.1
You're the best! Thanks! This worked for me!
I can confirm that this is working, i use reactjs-social-login==2.6.2 to obtain the access_code from google
django-allauth==0.50.0
dj-rest-auth==4.0.1
this is the response i get from reactjs-social-login
{
"access_token": "access_token",
"token_type": "Bearer",
"expires_in": 3599,
"scope": "email profile openid https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile",
"authuser": "0",
"prompt": "none",
"sub": "sub",
"name": "Me",
"given_name": "Me",
"family_name": "And I",
"picture": "url",
"email": "email@gmail.com",
"email_verified": true,
"locale": "en"
}
my backend looks like this, no config needed:
from dj_rest_auth.registration.views import SocialLoginView
from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter
class GoogleLogin(SocialLoginView):
adapter_class = GoogleOAuth2Adapter
Hope it will help someone!
As of Aug, 08, 2023, with django-allauth latest version 0.54.0 it seems to have a bug that results in function being unable to pass user identity to other funcitons, resulting in a frustrating code breake. If you face this error it can be worked around by a downgrade, pip install django-allauth==0.50.0
to resolve an issue with allauth library that results in error The above exception (not enough values to unpack (expected 2, got 1))
. Issue in hand is with a response["id_token"]
which in upgraded version the new function seems to have change unpack parameters, but older version 0.50.0 works fine.
This is an annoying and poorly documented error, so notes came handy to work arround until bug is fixed:
Environment Information for reproducing this error: Django version: 3.2.18 Python version 3.11.4 django-allauth 0.54.0 google-auth 2.21.0 google-auth-httplib2 0.1.0 google-auth-oauthlib 1.0.0 googleapis-common-protos 1.59.1 djangorestframework 3.14.0 djangorestframework-simplejwt 5.2.2 dj-rest-auth 4.0.1
Trying to hook oauth using a simple general GoogleLogin
function to call Google Oauth api with library resources returns an error response suggesting an invalid token id.
class GoogleLogin(SocialLoginView):
adapter_class = GoogleOAuth2Adapter
Calling api http://127.0.0.1:8000/api/rest-auth/google/
with provided credentials generated at Google Playground will result in an Invalid Token error.
{
"access_token": <access_token>,
"id_token": <id_token>,
"expires_in": 3599,
"token_type": "Bearer",
"scope": "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile openid",
"refresh_token": <refresh_token>
}
The above exception (not enough values to unpack (expected 2, got 1)) was the direct cause of the following exception: /opt/venv//lib/python3.11/site-packages/allauth/socialaccount/providers/google/views.py, line 42, in complete_login*
class GoogleOAuth2Adapter(OAuth2Adapter):
provider_id = GoogleProvider.id
access_token_url = ACCESS_TOKEN_URL
authorize_url = AUTHORIZE_URL
id_token_issuer = ID_TOKEN_ISSUER
def complete_login(self, request, app, token, response, **kwargs):
try:
identity_data = jwt.decode(
response["id_token"],
# Since the token was received by direct communication
# protected by TLS between this library and Google, we
# are allowed to skip checking the token signature
# according to the OpenID Connect Core 1.0
# specification.
# https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
options={
"verify_signature": False,
"verify_iss": True,
"verify_aud": True,
"verify_exp": True,
},
issuer=self.id_token_issuer,
audience=app.client_id,
)
except jwt.PyJWTError as e:
raise OAuth2Error("Invalid id_token") from e
login = self.get_provider().sociallogin_from_response(request, identity_data)
return login
Class handeling this in version 0.50.0 seems to work fine:
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"
def complete_login(self, request, app, token, **kwargs):
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
The changes between the versions seem to reflect a transition from a simple OAuth 2.0 flow (where user data is fetched from the provider) to an OpenID Connect flow (where user identity information is embedded in the id_token). The OpenID Connect is an extension of OAuth 2.0 and provides richer identity features.
However, as with any update, there might be some changes in the library's internal handling that could lead to the issue. As there seems to be a bug or unexpected behavior in the newer version that resulted in the "not enough values to unpack" error, downgrading to the older version that doesn't have this issue is a reasonable short-term fix. Always good to monitor the library for any patches or updates that address the issue in future versions.
I hope this detailed report helps others facing similar issues and aids in the quicker resolution of this bug. Thank you to the community and maintainers for their continuous efforts in maintaining and improving this library.
I was working through @duplxey's excellent tutorial article on Django REST Framework Authentication with Auth.js, and ran into this issue.
I wanted to note that duplexy has two similar example apps:
The new app uses:
django-allauth==0.54.0
dj-rest-auth==4.0.1
@DerekHill thanks for that, this allauth <--> dj-rest-auth gave me some awful headache
While trying to implement the previous guide (https://testdriven.io/blog/django-rest-authjs/), my team also faced some of the issues described above:
versions mismatch between django-allauth and dj-rest-auth In the end, using version 0.54.0 (allauth) and 4.0.1 (dj-rest-auth) as suggested above seemed to work but these are not the latest versions of these packages which we would like to use
passing the id_token in the access_token field was the only way we managed to properly authenticate with the backend. Is this intended? Will it change in the future?
@ap-pjgr, it works if you pass both access_token
and id_token
. Tested with dj-rest-auth==5.0.2
and django-allauth==0.57.0
.
See this piece of code (id_token
is used only if access_token
is present):
https://github.com/iMerica/dj-rest-auth/blob/23f097cebcc8ecef886b2ac7869cc1d51f66f90e/dj_rest_auth/registration/serializers.py#L100-L154
Thanks @DerekHill for the tip. I took the latest version of @duplxey, and only with these specific versions the thing worked, and now i'm able to login with google authorization. btw it works also with the latest django, not only 4.23 as mentioned in his requirements.txt . The thing is, the whole thing is a bit fragile. so many libraries are involved, and it only works in very specific versions... and there's lots of black magic behind it. I'm a bit worried to use this in production.
django-allauth==0.50.0
Thank you so much ❤️
@ap-pjgr, it works if you pass both
access_token
andid_token
. Tested withdj-rest-auth==5.0.2
anddjango-allauth==0.57.0
.See this piece of code:
Yes, you can use the Google OAuth 2.0 Playground to get your ID Token and Access Token. This post can help you: https://duizendstra.medium.com/how-to-easily-obtain-a-google-id-token-f1cde61541f0
Confirmed to work on the following version combination by passing both access_token
and id_token
in the POST to the backend Google views.
dj-rest-auth==5.0.2
Django==4.2.2
django-allauth==0.57.0
Was this a bug before or is it a bug now? They are sparse, but any writeup I've read on this topic passes id_token
as access_token
in the backend POST. That seemed strange to me when I read it initially. Perhaps the current behaviors not a bug but is rather the intended design. Can anyone confirm or clarify?
Honestly, the whole id/access token is a bit opaque. Perhaps I needs to read some more in-depth discussions on this authentication architecture.
django-allauth==0.50.0
Yea this worked for me. Specifically, the following:
from dj_rest_auth.registration.views import SocialLoginView
from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter
from allauth.socialaccount.providers.oauth2.client import OAuth2Client
class GoogleLogin(SocialLoginView):
adapter_class = GoogleOAuth2Adapter
callback_url = "http://127.0.0.1:3000/"
client_class = OAuth2Client
def post(self, request, *args, **kwargs):
print(f"Request data: {request.data}")
request.data["id_token"] = request.data.get("access_token")
return super().post(request, *args, **kwargs)
Seems like a bug.
The root cause of this issue is that starting from 0.52.0, django-allauth is using the ID token for extracting user information. The ID token is handed over together with the access token as part of the Google OAuth handshake, so with just the django-allauth scope in mind there is no need to make additional calls to fetch user information. However, in a broader scope, this does break the dj-rest-auth use case, causing this issue.
In order to get this issue resolved, django-allauth has been changed to make a call to the userinfo endpoint in case no ID token is present. This change landed on version 0.61.0. However, dj-rest-auth is currently using this for its dependencies:
extras_require={
'with_social': ['django-allauth>=0.56.0,<0.58.0'],
},
Given the amount of people impacted by this, I also backported that change to version 0.57.1 so that there is a version of dj-rest-auth that is compatible with a version of django-allauth containing the fix. This version has just been released. I do hope that current limitation of <0.58.0
gets resolved in a future release of dj-rest-auth, but at least on the short term we can now all move forward.
Hope this helps!
Thanks to @pennersr the maintainer of django-allauth using a significant time to investigate this long term issue on our backend/app and push this to a solution that will hopefully benefit all users of django-allauth and dj-rest-auth. Forever grateful!
I was getting an issue with this too. What was happening was: when the frontend sends the access_token to the GoogleLogin endpoin as "token" earlier version of dj-rest-auth (2.2.4, 2.2.6) the response would be a "refresh_token", "access_token" and "user" object.
newer dj-rest-auth versions was causing the response to be just {"key":"xxxxxxxxxxxxxxxxxxx"}.
my frontend was expecting the older format "access_token" "refresh_token" and user object. not "key". I didnt even know what to do with the key value.
So I downgraded to allauth 0.50 and dj-rest-auth 2.2.6 and it is working fine again.
I've been chasing this issue for the last few hours with the latest versions of Allauth (0.61.1) and dj-rest-auth (5.0.2) and by debugging both libraries, the underlying issue was being caused by the exception described here - https://github.com/jpadilla/pyjwt/issues/814, where when the OAuth2 token was attempted to be used within ms of being granted, it would fail.
As suggested in that thread, re-syncing my Windows clock actually fixed it. So throwing this here in case it's helpful to anyone else in the future.
PS: Thanks again to pennersr for everything you do!
So update to the above. Even with re-syncing my Windows clock every few hours, this is still pretty flakey and is still failing about 50% of the time. It seems even a delta of a few MS will throw this off.
So this is what I came up with, and it seems to be much more reliable (even manually setting my local time back by a minute and increasing the allowed delta_time
window to 90 to accommodate it, the request, while taking over a minute, doesn't fail).
class GoogleOAuth2IatValidationAdapter(GoogleOAuth2Adapter):
def complete_login(self, request, app, token, response, **kwargs):
try:
delta_time = (
jwt.decode(
response.get("id_token"),
options={"verify_signature": False},
algorithms=["RS256"],
)["iat"]
- time()
)
except jwt.PyJWTError as e:
raise OAuth2Error("Invalid id_token during 'iat' validation") from e
except KeyError as e:
raise OAuth2Error("Failed to get 'iat' from id_token") from e
# Or change 30 to whatever you feel is a maximum amount of time you are willing to wait
if delta_time > 0 and delta_time <= 30:
sleep(delta_time)
return super().complete_login(request, app, token, response, **kwargs)
class GoogleLoginView(SocialLoginView):
adapter_class = GoogleOAuth2IatValidationAdapter
...
The JWT is still fully validated as part of the super().complete_login
so this shouldn't compromise the JWT AFAIK, but having a sleep
call in a request isn't my favourite. If anyone has an alternative solution/suggestion lmk but I'll see how reliable this is over the next few days.
What exactly is the resolution for this? I am also getting the ""Failed to exchange code for access token" error and I don't know why. There at least has to be better debug output for this, and it should be fixed.
More information on the issue
As of Aug, 08, 2023, with django-allauth latest version 0.54.0 it seems to have a bug that results in function being unable to pass user identity to other funcitons, resulting in a frustrating code breake. If you face this error it can be worked around by a downgrade,
pip install django-allauth==0.50.0
to resolve an issue with allauth library that results in errorThe above exception (not enough values to unpack (expected 2, got 1))
. Issue in hand is with aresponse["id_token"]
which in upgraded version the new function seems to have change unpack parameters, but older version 0.50.0 works fine.
It worked for me, thank you very much.
I'm using
dj-rest-auth
on the backend and NextAuth.js on the frontend. After successfully logging in via NextAuth.js I get the followingaccount
passed to mysignIn
callback:{ provider: "google", type: "oauth", providerAccountId: "177780422328299215542", access_token: "%access_token%", expires_at: 1682337884, refresh_token: "%refresh_token%", scope: "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile openid", token_type: "Bearer", id_token: "%id_token%" }
1. `access_token` is a random string of characters. Not decodable by jwt.io. 2. `id_token` is a JWT token (`header.payload.signature`). It is decodable by jwt.io.
I then forward the
access_token
andid_token
to mydj-rest-auth
Google endpoint defined like this:from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter from allauth.socialaccount.providers.oauth2.client import OAuth2Client, OAuth2Error from dj_rest_auth.registration.views import SocialLoginView class GoogleLogin(SocialLoginView): # Authorization Code grant adapter_class = GoogleOAuth2Adapter callback_url = "http://localhost:3000/api/auth/callback/google" client_class = OAuth2Client
I use the following request code:
const options = { method: 'POST', url: 'http://127.0.0.1:8000/api/auth/google/', headers: { 'Content-Type': 'application/json' }, data: { access_token: '%access_token%', id_token: '%id_token%' } }; axios.request(options).then(function (response) { console.log(response.data); }).catch(function (error) { console.error(error); });
This request fails with an error saying:
Not enough segments Internal Server Error: /api/auth/google/ Traceback (most recent call last): File ".\venv\lib\site-packages\jwt\api_jws.py", line 251, in _load header_segment, payload_segment = signing_input.split(b".", 1) ValueError: not enough values to unpack (expected 2, got 1) The above exception was the direct cause of the following exception: Traceback (most recent call last): File ".\authentication\views.py", line 33, in complete_login identity_data = jwt.decode( File ".\venv\lib\site-packages\jwt\api_jwt.py", line 168, in decode decoded = self.decode_complete( File ".\venv\lib\site-packages\jwt\api_jwt.py", line 120, in decode_complete decoded = api_jws.decode_complete( File ".\venv\lib\site-packages\jwt\api_jws.py", line 191, in decode_complete payload, signing_input, header, signature = self._load(jwt) File ".\venv\lib\site-packages\jwt\api_jws.py", line 253, in _load raise DecodeError("Not enough segments") from err jwt.exceptions.DecodeError: Not enough segments The above exception was the direct cause of the following exception: Traceback (most recent call last): File ".\venv\lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) File ".\venv\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File ".\venv\lib\site-packages\django\views\decorators\csrf.py", line 56, in wrapper_view return view_func(*args, **kwargs) File ".\venv\lib\site-packages\django\views\generic\base.py", line 104, in view return self.dispatch(request, *args, **kwargs) File ".\venv\lib\site-packages\django\utils\decorators.py", line 46, in _wrapper return bound_method(*args, **kwargs) File ".\venv\lib\site-packages\django\views\decorators\debug.py", line 92, in sensitive_post_parameters_wrapper return view(request, *args, **kwargs) File ".\venv\lib\site-packages\dj_rest_auth\views.py", line 48, in dispatch return super().dispatch(*args, **kwargs) File ".\venv\lib\site-packages\rest_framework\views.py", line 509, in dispatch response = self.handle_exception(exc) File ".\venv\lib\site-packages\rest_framework\views.py", line 469, in handle_exception self.raise_uncaught_exception(exc) File ".\venv\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception raise exc File ".\venv\lib\site-packages\rest_framework\views.py", line 506, in dispatch response = handler(request, *args, **kwargs) File ".\venv\lib\site-packages\dj_rest_auth\views.py", line 125, in post self.serializer.is_valid(raise_exception=True) File ".\venv\lib\site-packages\rest_framework\serializers.py", line 227, in is_valid self._validated_data = self.run_validation(self.initial_data) File ".\venv\lib\site-packages\rest_framework\serializers.py", line 429, in run_validation value = self.validate(value) File ".\venv\lib\site-packages\dj_rest_auth\registration\serializers.py", line 151, in validate login = self.get_social_login(adapter, app, social_token, response={'id_token': token}) File ".\venv\lib\site-packages\dj_rest_auth\registration\serializers.py", line 60, in get_social_login social_login = adapter.complete_login(request, app, token, response=response) File ".\authentication\views.py", line 46, in complete_login raise OAuth2Error("Invalid id_token") from e allauth.socialaccount.providers.oauth2.client.OAuth2Error: Invalid id_token
After some testing I figured out that
response["id_token"]
incomplete_login
returns the request'saccess_token
and not theid_token
.print(response["id_token"]) # prints out {'id_token': '%access_token%'}
Sending your
id_token
as theaccess_token
without providingid_token
seems to work:const options = { method: 'POST', url: 'http://127.0.0.1:8000/api/auth/google/', headers: { 'Content-Type': 'application/json' }, data: { access_token: '%id_token%' } }; axios.request(options).then(function (response) { console.log(response.data); }).catch(function (error) { console.error(error); });
Is this the expected behaviour? Am I missing something?
The problem is with django-allauth versions ,the newer versions seems to have a bug arround id_token, I downgraded django-allauth==0.62.1 to django-allauth==0.57.0 and this worked with django-rest-auth==6.0.0
Hello, How to solve "Failed to exchange code for access token" When sending {"code": "code from google"} on postman ?
I'm using
dj-rest-auth
on the backend and NextAuth.js on the frontend. After successfully logging in via NextAuth.js I get the followingaccount
passed to mysignIn
callback:access_token
is a random string of characters. Not decodable by jwt.io.id_token
is a JWT token (header.payload.signature
). It is decodable by jwt.io.I then forward the
access_token
andid_token
to mydj-rest-auth
Google endpoint defined like this:I use the following request code:
This request fails with an error saying:
After some testing I figured out that
response["id_token"]
incomplete_login
returns the request'saccess_token
and not theid_token
.Sending your
id_token
as theaccess_token
without providingid_token
seems to work:Is this the expected behaviour? Am I missing something?