django-allauth对接Google登录时,已申请的额外用户字段未存入extra_data
问题根因
- 当前使用的
django-allauthGoogle登录适配器,默认仅从Google基础userinfo接口拉取固定范围的基础字段,不会主动请求你在scope中申请的高阶权限对应的专属资源。 - 你配置的
user.birthday.read、user.addresses.read、profile.agerange.read这类scope,对应的是Google People API的专属数据范畴,并非基础userinfo接口的返回内容。哪怕授权流程完全顺畅,只要适配器不主动调用People API的对应端点拉取数据,这些字段就不会出现在extra_data中。 - 对比Facebook的适配逻辑:Facebook的适配器本身实现了配置字段和Graph API请求参数的映射,你在
FIELDS中声明什么字段,适配器就会自动拼接请求参数到Graph API接口拉取对应数据,因此可以完整拿到所有配置的字段,和Google的默认逻辑存在本质差异。 - 额外的常见触发因素:Google OAuth会缓存历史授权记录,如果你之前已经完成过一次Google登录,系统会复用旧的access token,这类旧token的权限范围是缺失后续新增的高阶scope的,哪怕代码里更新了scope配置,也实际拿不到对应权限。
解决方案
- 第一步:校验实际token的权限范围
拿到Google返回的access token后,调用token校验接口,核对返回的scope列表是否真的包含你申请的所有高阶权限。如果权限缺失,需要先在对应Google Cloud项目中启用People API服务,同步更新OAuth同意页的权限范围,测试阶段未审核的OAuth应用,默认无法获取超出基础范围的用户权限。 - 第二步:自定义Google适配器,主动拉取高阶字段
django-allauth的默认Google适配器没有实现高阶字段的拉取逻辑,需要重写适配器的登录完成流程,在拿到用户基础信息后,用已获取的access token主动调用People API的people/me端点,将返回的生日、地址、年龄范围等字段合并存入extra_data。
示例代码:
新建allauth_adapters.py文件:
在import requests from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter from allauth.socialaccount.providers.google.provider import GoogleProvider class CustomGoogleAdapter(GoogleOAuth2Adapter): def complete_login(self, request, app, token, response, **kwargs): login = super().complete_login(request, app, token, response, **kwargs) # 完成基础登录流程后,拉取高阶用户字段 people_api_resp = requests.get( "https://people.googleapis.com/v1/people/me", params={ "personFields": "birthdays,addresses,ageRanges,genders,phoneNumbers", "access_token": token.token }, timeout=10 ) people_data = people_api_resp.json() # 合并字段到extra_data login.account.extra_data.update({ "birthday": people_data.get("birthdays"), "addresses": people_data.get("addresses"), "age_range": people_data.get("ageRanges"), "gender": people_data.get("genders"), "phone_numbers": people_data.get("phoneNumbers") }) login.account.extra_data.save() return login class CustomGoogleProvider(GoogleProvider): id = GoogleProvider.id name = GoogleProvider.name adapter_class = CustomGoogleAdaptersettings.py中替换默认Google provider配置:SOCIALACCOUNT_PROVIDERS = { # ... 保留原有Facebook配置不变 "google": { "SCOPE": [ 'https://www.googleapis.com/auth/userinfo.profile', 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/user.emails.read', 'https://www.googleapis.com/auth/user.phonenumbers.read', 'https://www.googleapis.com/auth/user.birthday.read', 'https://www.googleapis.com/auth/profile.agerange.read', 'https://www.googleapis.com/auth/user.addresses.read', ], "AUTH_PARAMS": { "access_type": "online", } } } # 注册自定义provider替换默认实现 SOCIALACCOUNT_PROVIDERS.update({ "google": CustomGoogleProvider }) - 第三步:强制重新授权避免缓存
因为Google会缓存历史授权结果,测试时可以在Google的授权参数中增加prompt: "consent",强制每次登录都弹出权限同意页,确保拿到的access token包含所有申请的权限范围,避免复用旧的无权限token:# settings.py中Google部分的AUTH_PARAMS修改 "AUTH_PARAMS": { "access_type": "online", "prompt": "consent" }
内容的提问来源于stack exchange,提问作者Ali Aref
相关产品推荐
相关产品推荐

