重新实现社交登录(在Django中)

时间:2018-11-03 22:26:27

标签: django oauth google-oauth facebook-oauth python-social-auth

TL; DR:是否可以不存储(Google / Facebook)OAuth2访问令牌,而是在每次登录时请求新令牌?

我会解释:

要将社交登录名(“使用Google / Facebook登录”)添加到Django应用中,您必须拥有Python Social Auth。至少对我而言,它的问题在于它比我想要的复杂得多,需要大量配置,在数据库中创建其他表,并且总体上感觉很多我不理解的活动部分完成一个非常简单的任务。

所以,我读了一些关于Google'sFacebook's流的信息,它们很简单:

  • 服务器具有 ID 秘密
  • 客户端/用户具有其标准登录凭据。

然后:

  1. 服务器将用户重定向到Google / Facebook,并提供其 ID 重定向URI
  2. 用户登录后,Google / Facebook使用代码将其重定向到该URI。
  3. 服务器将其 ID 秘密和接收的代码发送到Google / Facebook,并获得访问令牌< / strong>作为交换,它现在可以用来代表用户进行API调用。
  4. 即使是最基本的权限也足以在Google / Facebook上查询用户的电子邮件,然后可以将其与Django的标准用户模型匹配(如果不存在,则可以创建无密码用户)。

现在可以丢弃访问令牌,因为只需要将Google / Facebook登录名转换为实际的电子邮件(由他们验证)即可,该电子邮件仅用作 用户标识符-否通过不同的社交服务登录时,由于帐户不同而造成的更多混乱;没有其他表格;没有不必要的复杂性。

这是代码,只是为了显示所需的内容:

# views.py

def login_view(request):
    return render(request, 'login.html', {
        'google_url': 'https://accounts.google.com/o/oauth2/v2/auth?' + urllib.parse.urlencode({
            'client_id': GOOGLE_ID,
            'redirect_uri': request.build_absolute_uri(reverse('oauth_google')),
            'scope': 'profile email',
            'response_type': 'code',
        }),
    }) # use this url in the template as a social login

def oauth_google(request):
    code = request.GET['code']
    response = requests.post('https://www.googleapis.com/oauth2/v4/token', {
        'code': code,
        'client_id': GOOGLE_ID,
        'client_secret': GOOGLE_SECRET,
        'redirect_uri': request.build_absolute_uri(reverse('oauth_google')),
        'grant_type': 'authorization_code',
    }).json()
    id_token = response['id_token']
    response = requests.get('https://www.googleapis.com/oauth2/v3/tokeninfo', {
        'id_token': id_token,
    }).json()
    email = response['email']
    user = User.objects.filter(username=email).first()
    if not user:
        user = User(username=email)
        user.save()
    auth.login(request, user)
    return redirect('index')

# urls.py

urlpatterns = [
    ...
    path('oauth/google', views.oauth_google, name='oauth_google'),
]

我的问题是:我想念什么?如果真的那么简单,为什么我在网上的StackOverflow /教程中找不到任何答案呢?

我能想到的唯一原因是访问令牌带有到期时间(在1小时到60天之间的任何时间);因此,也许我应该一直在重复使用相同的访问令牌,只要它是有效的(这将需要存储它,并将解释为什么Python Social Auth需要额外的表)。 Google / Facebook是否会因为太频繁地请求新的访问令牌而使我生气并阻止我?我在他们的文档中找不到任何提及。

编辑

这是Facebook代码,以防万一有人发现这些片段有用:

# views.py

def login_view(request):
    return render(request, 'login.html', {
        'facebook_url': 'https://www.facebook.com/v3.2/dialog/oauth?' + urllib.parse.urlencode({
            'client_id': FACEBOOK_ID,
            'redirect_uri': request.build_absolute_uri(reverse('oauth_facebook')),
            'scope': 'email',
        }),
    }) # use this url in the template as a social login

def oauth_facebook(request):
    code = request.GET['code']
    response = requests.get('https://graph.facebook.com/v3.2/oauth/access_token', {
        'code': code,
        'client_id': FACEBOOK_ID,
        'client_secret': FACEBOOK_SECRET,
        'redirect_uri': request.build_absolute_uri(reverse('oauth_facebook')),
    }).json()
    access_token = response['access_token']
    response = requests.get('https://graph.facebook.com/me', {
        'access_token': access_token,
        'fields': 'email',
    }).json()
    email = response['email']
    user = User.objects.filter(username=email).first()
    if not user:
        user = User(username=email)
        user.save()
    auth.login(request, user)
    return redirect('index')

# urls.py

urlpatterns = [
    ...
    path('oauth/facebook', views.oauth_facebook, name='oauth_facebook'),
]

0 个答案:

没有答案