mirror of https://github.com/jumpserver/jumpserver
fix: OpenID Only allow existing users to log in operate log error
parent
a732cc614e
commit
5c66b3524a
|
@ -134,6 +134,7 @@ class OIDCAuthCallbackView(View, FlashMessageMixin):
|
|||
log_prompt = "Process GET requests [OIDCAuthCallbackView]: {}"
|
||||
logger.debug(log_prompt.format('Start'))
|
||||
callback_params = request.GET
|
||||
error_title = _("OpenID Error")
|
||||
|
||||
# Retrieve the state value that was previously generated. No state means that we cannot
|
||||
# authenticate the user (so a failure should be returned).
|
||||
|
@ -172,10 +173,9 @@ class OIDCAuthCallbackView(View, FlashMessageMixin):
|
|||
try:
|
||||
user = auth.authenticate(nonce=nonce, request=request, code_verifier=code_verifier)
|
||||
except IntegrityError as e:
|
||||
title = _("OpenID Error")
|
||||
msg = _('Please check if a user with the same username or email already exists')
|
||||
logger.error(e, exc_info=True)
|
||||
response = self.get_failed_response('/', title, msg)
|
||||
response = self.get_failed_response('/', error_title, msg)
|
||||
return response
|
||||
if user:
|
||||
logger.debug(log_prompt.format('Login: {}'.format(user)))
|
||||
|
@ -194,7 +194,6 @@ class OIDCAuthCallbackView(View, FlashMessageMixin):
|
|||
return HttpResponseRedirect(
|
||||
next_url or settings.AUTH_OPENID_AUTHENTICATION_REDIRECT_URI
|
||||
)
|
||||
|
||||
if 'error' in callback_params:
|
||||
logger.debug(
|
||||
log_prompt.format('Error in callback params: {}'.format(callback_params['error']))
|
||||
|
@ -205,9 +204,12 @@ class OIDCAuthCallbackView(View, FlashMessageMixin):
|
|||
# OpenID Connect Provider authenticate endpoint.
|
||||
logger.debug(log_prompt.format('Logout'))
|
||||
auth.logout(request)
|
||||
|
||||
redirect_url = settings.AUTH_OPENID_AUTHENTICATION_FAILURE_REDIRECT_URI
|
||||
if not user and getattr(request, 'error_message', ''):
|
||||
response = self.get_failed_response(redirect_url, title=error_title, msg=request.error_message)
|
||||
return response
|
||||
logger.debug(log_prompt.format('Redirect'))
|
||||
return HttpResponseRedirect(settings.AUTH_OPENID_AUTHENTICATION_FAILURE_REDIRECT_URI)
|
||||
return HttpResponseRedirect(redirect_url)
|
||||
|
||||
|
||||
class OIDCAuthCallbackClientView(BaseAuthCallbackClientView):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
import inspect
|
||||
import threading
|
||||
import time
|
||||
import uuid
|
||||
from functools import partial
|
||||
|
@ -12,6 +13,7 @@ from django.contrib.auth import (
|
|||
BACKEND_SESSION_KEY, load_backend,
|
||||
PermissionDenied, user_login_failed, _clean_credentials,
|
||||
)
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.shortcuts import reverse, redirect, get_object_or_404
|
||||
|
@ -46,6 +48,10 @@ def _get_backends(return_tuples=False):
|
|||
return backends
|
||||
|
||||
|
||||
class OnlyAllowExistUserAuthError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
auth._get_backends = _get_backends
|
||||
|
||||
|
||||
|
@ -54,6 +60,24 @@ def authenticate(request=None, **credentials):
|
|||
If the given credentials are valid, return a User object.
|
||||
之所以 hack 这个 authenticate
|
||||
"""
|
||||
|
||||
UserModel = get_user_model()
|
||||
original_get_or_create = UserModel.objects.get_or_create
|
||||
|
||||
thread_local = threading.local()
|
||||
thread_local.thread_id = threading.get_ident()
|
||||
|
||||
def custom_get_or_create(self, *args, **kwargs):
|
||||
logger.debug(f"get_or_create: thread_id={threading.get_ident()}, username={username}")
|
||||
if threading.get_ident() != thread_local.thread_id or not settings.ONLY_ALLOW_EXIST_USER_AUTH:
|
||||
return original_get_or_create(*args, **kwargs)
|
||||
create_username = kwargs.get('username')
|
||||
try:
|
||||
UserModel.objects.get(username=create_username)
|
||||
except UserModel.DoesNotExist:
|
||||
raise OnlyAllowExistUserAuthError
|
||||
return original_get_or_create(*args, **kwargs)
|
||||
|
||||
username = credentials.get('username')
|
||||
|
||||
temp_user = None
|
||||
|
@ -71,10 +95,19 @@ def authenticate(request=None, **credentials):
|
|||
# This backend doesn't accept these credentials as arguments. Try the next one.
|
||||
continue
|
||||
try:
|
||||
UserModel.objects.get_or_create = custom_get_or_create.__get__(UserModel.objects)
|
||||
user = backend.authenticate(request, **credentials)
|
||||
except PermissionDenied:
|
||||
# This backend says to stop in our tracks - this user should not be allowed in at all.
|
||||
break
|
||||
except OnlyAllowExistUserAuthError:
|
||||
request.error_message = _(
|
||||
'''The administrator has enabled "Only allow existing users to log in",
|
||||
and the current user is not in the user list. Please contact the administrator.'''
|
||||
)
|
||||
continue
|
||||
finally:
|
||||
UserModel.objects.get_or_create = original_get_or_create
|
||||
if user is None:
|
||||
continue
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ from common.utils import get_logger
|
|||
from common.utils.common import get_request_ip
|
||||
from common.utils.django import reverse, get_object_or_none
|
||||
from users.models import User
|
||||
from users.signal_handlers import check_only_allow_exist_user_auth, bind_user_to_org_role
|
||||
from users.signal_handlers import bind_user_to_org_role, check_only_allow_exist_user_auth
|
||||
from .mixins import FlashMessageMixin
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
@ -55,7 +55,6 @@ class BaseLoginCallbackView(AuthMixin, FlashMessageMixin, IMClientMixin, View):
|
|||
)
|
||||
|
||||
if not check_only_allow_exist_user_auth(create):
|
||||
user.delete()
|
||||
return user, (self.msg_client_err, self.request.error_message)
|
||||
|
||||
setattr(user, f'{self.user_type}_id', user_id)
|
||||
|
|
Loading…
Reference in New Issue