如何使用django-allauth集成谷歌一键登录?

5
如何将Google One Tap登录体验与django-allauth集成?
  1. django-allauth已经集成并且可以使用简单的用户名/密码进行登录。
  2. 我想要Google OneTap更好的用户体验,识别用户的验证过的Google帐户,并提供通过发送JWT身份验证令牌到Django来继续的选项。
  3. 尝试寻找最简单/最清洁的方法来使用OneTap令牌注册新用户账户并将其视为已验证。
感谢任何建议。
参考资料:
2个回答

1
我拼凑了一些东西,没有一个点击登录那么流畅(需要多一个步骤)。
在此处查看更多详细信息https://twitter.com/DataLeonWei/status/1368021373151375361 我所做的只是将谷歌重定向URL更改为现有的Google用户登录页面,并添加了一个额外的视图,并用此视图的URL替换了谷歌的data-login_uri。
@csrf_exempt
def google_one_tap_login(request):
    login_url = PUBLIC_DOMAIN_NAME + '/accounts/google/login/'
    return HttpResponseRedirect(login_url)

如果有更好的解决方案,请告诉我。
我的当前hack在sqlpadinstamentor上都实现了,欢迎查看并看到它的实际效果。

1
谢谢您的建议!我5个月前提出了这个问题,并找到了另一种解决方案(非OneTap),但如果我能确认它有效,我仍然有兴趣接受/批准这个解决方案。根据分享的Twitter截图,看起来很有前途。我会尽快尝试一下,看看是否能够复制您展示的功能。 - Michael
1
不用谢,很高兴能为您效劳。我的当前黑客实现在sqlpad网站上,请随意查看并观看它的运行。 - Leon Wei
1
确认这看起来很棒!将答案标记为已接受。再次感谢。 - Michael

1

覆盖 allauth 的 account/login.html 模板并呈现 Google 按钮(记得替换 <GOOGLE_APP_CLIENT_ID><HOMEPAGE>):

<div class="g_id_signin" data-type="standard" data-shape="pill"
     data-theme="outline" data-text="signin_with" data-size="large"
     data-logo_alignment="left"></div>

<div id="g_id_onload"
     data-client_id="<GOOGLE_APP_CLIENT_ID>"
     data-context="signin"
     data-ux_mode="redirect"
     data-login_uri="<HOMEPAGE>{% url 'google-login' %}?next={{ request.GET.next }}"
     data-auto_prompt="false"></div>

<script src="https://accounts.google.com/gsi/client" async defer></script>

如果您还没有安装,可以安装 google-auth

pip install google-auth

在你的urls.py中注册google-login端点:

path('google-login', views.google_login, name='google-login'),

在你的views.py中定义google-login端点,在重定向到allauth的Google登录URL之前,验证Google ID令牌

import logging
from django.conf import settings
from django.contrib import messages
from django.http import HttpResponseBadRequest
from django.shortcuts import redirect
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from google.oauth2 import id_token
from google.auth.transport import requests
from urllib import parse

@csrf_exempt
@require_POST
def google_login(request):
    body_unicode = request.body.decode('utf-8')
    body_params = parse.parse_qs(body_unicode)
    csrf_token_cookie = request.COOKIES.get('g_csrf_token')
    if not csrf_token_cookie:
        return HttpResponseBadRequest('No CSRF token in Cookie.')
    csrf_token_body = body_params.get('g_csrf_token')
    if not csrf_token_body:
        return HttpResponseBadRequest('No CSRF token in post body.')
    if csrf_token_cookie != csrf_token_body[0]:
        return HttpResponseBadRequest('Failed to verify double submit cookie.')
    next_url = request.GET['next']
    try:
        token = body_params.get('credential')[0]
        # noinspection PyUnusedLocal
        idinfo = id_token.verify_oauth2_token(token, requests.Request(), settings.GOOGLE_APP_CLIENT_ID)
    except ValueError as e:
        logging.error(e)
        return HttpResponseBadRequest('Failed to verify Google auth credentials.')
    return redirect(settings.HOMEPAGE + '/accounts/google/login/?next=' + next_url)

感谢您的建议。几年前曾询问过这个问题,并选择了不同的解决方案(非OneTap)。目前没有时间确认这是否有效,但很感激知道这个解决方案的存在。 - Michael
@Rok Strniša 这段代码没有显示“Google One Tap登录”。我在本地使用ngrok进行https。请告诉我是否还有其他需要做的事情来使您的代码工作? - Hariprasad
@Hariprasad 你是否用适当的值替换了GOOGLE_APP_CLIENT_ID和HOMEPAGE?在浏览器控制台或服务器日志中有看到任何信息吗? - Rok Strniša
@Rok Strniša 我已经替换了 GOOGLE_APP_CLIENT_ID 和 HOMEPAGE。我可以成功登录,但是没有用户被创建并且也没有用户会话。 - Hariprasad
@Hariprasad 我认为用户应该在第一次访问 /accounts/google/login/ 时创建,这也是在 google_login 结束时重定向到的位置。也许可以尝试通过覆盖 ACCOUNT_ADAPTERSOCIALACCOUNT_ADAPTER 进行调试。 - Rok Strniša

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