Auth0在自定义django身份验证后端登录错误的用户

时间:2019-07-23 17:38:26

标签: django django-admin auth0

我正在使用Django Admin页面来管理大型数据库的一些基本CRUD操作。我已经集成了用于登录/身份验证的Auth0,它也绕过了管理员登录页面,并基于Django的Auth0文档编写了自定义身份验证后端。

登录有时可以正常工作,重定向到Auth0社交身份验证登录,需要电子邮件和密码。但是,在其他时候,登录页面会被绕过,并重定向到管理员登录页面,以我本人以外的用户身份登录(我与正在自动登录的用户一起工作,他从未登录过我的本地计算机,但是作为用户位于Auth0和应用程序数据库中)。该应用程序的Auth0日志无法提供对该问题的任何见解。

我尝试使用提供的Auth0指南(使用“ social_django”应用程序和自定义身份验证后端应用程序)和“ allauth” django应用程序来启用身份验证部分,两者均产生相同的结果。我还将应用程序的JWT令牌设置为60秒,以确保它在尝试再次登录之前过期。

我不确定这是否是会话数据持久化的问题。我尚未设置会话后端,但确实知道django Admin需要会话中间件才能运行(我知道这一点是因为我尝试删除它,并提示出现错误,指出需要中间件)。

settings.py文件的相关部分如下所示:

# settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',
    'social_django',
    'auth0login',
    'app',
    'django_mysql',
    'rest_framework',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

AUTHENTICATION_BACKENDS = [

    'django.contrib.auth.backends.ModelBackend',
    'auth0login.auth0backend.Auth0',
]

SOCIAL_AUTH_TRAILING_SLASH = False  # Remove trailing slash from routes
SOCIAL_AUTH_AUTH0_DOMAIN = os.environ.get('AUTH0_DOMAIN')
SOCIAL_AUTH_AUTH0_KEY = os.environ.get('AUTH0_KEY')
SOCIAL_AUTH_AUTH0_SECRET = os.environ.get('AUTH0_SECRET')
SOCIAL_AUTH_AUTH0_SCOPE = [
    'openid',
    'profile',
    'email'
]
#
LOGIN_URL = '/login/auth0'
LOGIN_REDIRECT_URL = '/admin'
LOGOUT_REDIRECT_URL = '/admin'

SOCIAL_AUTH_PIPELINE = (
    'social_core.pipeline.social_auth.social_details',
    'social_core.pipeline.social_auth.social_uid',
    'social_core.pipeline.social_auth.auth_allowed',
    'social_core.pipeline.social_auth.social_user',
    'social_core.pipeline.user.get_username',
    'social_core.pipeline.user.create_user',
    'auth0login.authorization.process_roles',
    'social_core.pipeline.social_auth.associate_user',
    'social_core.pipeline.social_auth.load_extra_data',
    'social_core.pipeline.user.user_details',
)

身份验证后端显示在这里:

# auth0login/auth0backend.py
import requests
from jose import jwt
from social_core.backends.oauth import BaseOAuth2


class Auth0(BaseOAuth2):
    """Auth0 OAuth authentication backend"""
    name = 'auth0'
    SCOPE_SEPARATOR = ' '
    ACCESS_TOKEN_METHOD = 'POST'

    def authorization_url(self):
        return 'https://' + self.setting('DOMAIN') + '/authorize'

    def access_token_url(self):
        return 'https://' + self.setting('DOMAIN') + '/oauth/token'

    def get_user_id(self, details, response):
        """Return current user id."""
        return details['user_id']

    def get_user_details(self, response):
        # Obtain JWT and the keys to validate the signature
        id_token = response.get('id_token')
        jwks = requests.get('https://' + self.setting('DOMAIN') + '/.well-known/jwks.json')
        issuer = 'https://' + self.setting('DOMAIN') + '/'
        audience = self.setting('KEY')  # CLIENT_ID
        payload = jwt.decode(id_token, jwks.content, algorithms=['RS256'], audience=audience, issuer=issuer)

        return {'username': payload['nickname'],
                'first_name': payload['name'].split()[0],
                'last_name': payload['name'].split()[1],
                'user_id': payload['sub'],
                'email': payload['email'],
                }

Auth0login视图显示在这里:

# auth0login/views.py

from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.contrib.auth import logout as log_out
from django.conf import settings
from django.http import HttpResponseRedirect
from urllib.parse import urlencode

import json


def index(request):
    return render(request, 'index.html')


@login_required
def dashboard(request):
    user = request.user
    auth0user = user.social_auth.get(provider='auth0')
    userdata = {
        'user_id': auth0user.uid,
        'name': user.first_name,
    }

    return render(request, 'dashboard.html', {
        'auth0User': auth0user,
        'userdata': json.dumps(userdata, indent=4)
    })


def logout(request):
    log_out(request)
    return_to = urlencode({'returnTo': request.build_absolute_uri('/')})
    logout_url = 'https://%s/v2/logout?client_id=%s&%s' % \
                 (settings.SOCIAL_AUTH_AUTH0_DOMAIN, settings.SOCIAL_AUTH_AUTH0_KEY, return_to)
    return HttpResponseRedirect(logout_url)

最后,这是项目urls.py文件:

# urls.py
from django.contrib import admin
from django.urls import path, include, re_path
from django.views.generic.base import RedirectView
from django.conf import settings
# from app import views

admin.autodiscover()

urlpatterns = [
    path('', RedirectView.as_view(url=settings.LOGIN_URL, permanent=True, query_string=True)),
    path('', include('auth0login.urls')),
    re_path(r'^admin/login$', RedirectView.as_view(url=settings.LOGIN_URL, permanent=True, query_string=True)),
    path('admin/', admin.site.urls),
]

预期的输出是用户每次尝试登录时都会重定向到Auth0登录页面,然后在进行身份验证时重定向到管理页面。

0 个答案:

没有答案