【问题标题】:About Github OAuth authentication关于 Github OAuth 认证
【发布时间】:2013-07-20 06:42:54
【问题描述】:

我正在尝试通过我的 Django 网站上的 Github 进行身份验证。这是我想出的:

import string
import random
import urllib

from django.conf import settings
from django.core.urlresolvers import reverse
from django.shortcuts import redirect
from django.utils.crypto import constant_time_compare
from django.contrib.auth import login

from rauth import OAuth2Service
from mongoengine.django.auth import User

from utils import make_absolute


SESSION_KEY = '_oauth_access_token'
SESSION_STATE = '_oauth_state'

github = OAuth2Service(
    client_id=settings.GITHUB_APP_ID,
    client_secret=settings.GITHUB_API_SECRET,
    name='github',
    authorize_url='https://github.com/login/oauth/authorize',
    access_token_url='https://github.com/login/oauth/access_token',
    base_url='http://github.com/')


def random_string():
    return ''.join(random.choice(string.ascii_letters + string.digits)
                   for _ in xrange(random.randint(27, 49)))


def flush_and_set(request, key, value):
    if key in request.session:
        if request.session[key] != value:
            request.session.flush()
    else:
        request.session.cycle_key()
    request.session[key] = value


def start_pipeline(request):
    state = random_string()
    flush_and_set(request, SESSION_STATE, state)
    return redirect(github.get_authorize_url(
                        redirect_uri=make_absolute(reverse('auth-pipeline-end')),
                        state=state))


def end_pipeline(request):
    if not constant_time_compare(request.session[SESSION_STATE],
                                 request.GET['state']):
        return redirect('home')
    session = github.get_auth_session(data={'code': request.GET['code'],
                                            'redirect_uri':
                                            make_absolute(reverse('home'))})
    flush_and_set(request, SESSION_KEY, session.access_token)
    user_data = session.get('https://api.github.com/user?' +
                            urllib.urlencode({'access_token':
                                              session.access_token})).json()
    username = user_data['login']
    try:
        user = User.objects.get(username=username)
    except User.DoesNotExist:
        user = User(username=username)
    for field in ('email',):
        d = user_data[field]
        if d:
            setattr(user, field, d)
    user.backend = 'mongoengine.django.auth.MongoEngineBackend'
    user.save()
    login(request, user)
    return redirect('home')

我有两个问题:

  1. 这样做是否安全可靠?
  2. 我应该设置会话的到期时间吗?因为现在在我看来,它永远不会过期。

注意:我也在使用 rauth:https://rauth.readthedocs.org/en/latest/

【问题讨论】:

    标签: python django oauth


    【解决方案1】:

    不够安全,而且缺少一些细节。

      • 要获得更安全的状态值,请使用 SystemRandom
      • 您的会话是cookie based 吗?它们不会是默认的,也不应该是。
      • 重定向返回是否受 HTTPS 保护?
      • 您对 GitHub 的所有请求都是通过 HTTPS 吗?也获得token后?
    1. 默认到期时间为 2 周,但 OAuth 2 访问令牌通常会更快到期。不过,我相信 GitHub 令牌永远不会过期,因此改进方法是在关闭时使会话过期,在不再需要时使 delete the token 过期。

    也就是说,我强烈建议您使用 python-social-auth 而不是滚动您自己的 GitHub 登录名,因为该项目已经有更多人关注它并且已经有一段时间了。

    【讨论】:

    • 感谢您的回答!所以不,会话不是基于 cookie 的(我知道它们应该是?)。我的网站不在 HTTPS 上,但是对 Github 的所有请求都在 HTTPS 上。我之前使用过 django-social-auth,但是遇到了问题,我选择推出自己的解决方案(我只需要 Github 登录)。也许我会再试一次。
    • 它们不应该基于 cookie,将编辑答案。此外,如果您的网站不在 https 上,则可能会嗅探身份验证代码并用于获取访问令牌,如果他们设法窃取/猜测您的客户端密码。
    • 如果您不使用 HTTPS,当然还有许多其他攻击,所以如果您要使用 OAuth 2,请使用 HTTPS。
    • 感谢您的建议。我会为我的域研究 HTTPS。
    猜你喜欢
    • 2019-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多