Django Rest框架中的Allauth认证

9

我已经使用Allauth实现了Django Rest Auth,如果我通过Google access_token登录,则一切正常,但是有一个情况:某些客户端设备需要通过Google id_token进行登录。

如果我使用id_token而不是access_token,则会出现错误。

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

请帮我一下


你能提供更多的上下文吗?请求有效载荷?网址?等等。 - mariodev
你最终解决了这个问题吗? - Brendan
我得到了相同的错误。 - Umar Asghar
1
你是如何从谷歌获取access_token的? - Umar Asghar
你最终解决了这个问题吗? - giveJob
1个回答

2

更新您的文件,例如

../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)

使用id_token您仅会获取这些字段(access_type,audience,email,email_verified,expires_in,issued_at,issued_to,issuer,nonce,scope,user_id,verified_email)。因此,如果您的用户表需要电话姓名,您可以将它们设置为空name=''等。为此,您可以使用以下代码。

将用户模型所需的字段设置为空以覆盖id_token情况

这取决于您的用户模型,在我的情况下,我们需要电话和姓名,因此我将它们设置为空。如果您不这样做,您将获得失败的约束错误。

../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
        ....

我已将用户名设置为从社交平台 API 获取的用户 ID。稍后我强制用户更新其详细信息(用户名、姓名、电话等)。


1
嘿..我是django的新手。正在逐渐掌握要领。你能告诉我在哪里进行这些更改吗?是不是应该根据allauth编写一个自定义提供者? - pravin
你需要自定义Django-allauth库本身。 - Umar Asghar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接