mirror of
https://github.com/dkmstr/openuds.git
synced 2024-12-22 13:34:04 +03:00
Refactor authentication logging to include error flag
This commit is contained in:
parent
c67eee8b73
commit
c7666bb4f2
@ -160,7 +160,7 @@ class InternalDBAuth(auths.Authenticator):
|
||||
try:
|
||||
user: 'models.User' = dbAuth.users.get(name=username, state=State.ACTIVE)
|
||||
except Exception:
|
||||
log_login(request, self.db_obj(), username, 'Invalid user')
|
||||
log_login(request, self.db_obj(), username, 'Invalid user', as_error=True)
|
||||
return types.auth.FAILED_AUTH
|
||||
|
||||
if user.parent: # Direct auth not allowed for "derived" users
|
||||
@ -171,7 +171,7 @@ class InternalDBAuth(auths.Authenticator):
|
||||
groups_manager.validate([g.name for g in user.groups.all()])
|
||||
return types.auth.SUCCESS_AUTH
|
||||
|
||||
log_login(request, self.db_obj(), username, 'Invalid password')
|
||||
log_login(request, self.db_obj(), username, 'Invalid password', as_error=True)
|
||||
return types.auth.FAILED_AUTH
|
||||
|
||||
def get_groups(self, username: str, groups_manager: 'auths.GroupsManager') -> None:
|
||||
|
@ -168,6 +168,7 @@ class RadiusAuth(auths.Authenticator):
|
||||
self.db_obj(),
|
||||
username,
|
||||
'Access denied by Raiuds',
|
||||
as_error=True,
|
||||
)
|
||||
return types.auth.FAILED_AUTH
|
||||
|
||||
|
@ -381,7 +381,7 @@ class RegexLdap(auths.Authenticator):
|
||||
usr = self._get_user(username)
|
||||
|
||||
if usr is None:
|
||||
log_login(request, self.db_obj(), username, 'Invalid user')
|
||||
log_login(request, self.db_obj(), username, 'Invalid user', as_error=True)
|
||||
return types.auth.FAILED_AUTH
|
||||
|
||||
try:
|
||||
@ -390,7 +390,7 @@ class RegexLdap(auths.Authenticator):
|
||||
usr['dn'], credentials
|
||||
) # Will raise an exception if it can't connect
|
||||
except Exception:
|
||||
log_login(request, self.db_obj(), username, 'Invalid password')
|
||||
log_login(request, self.db_obj(), username, 'Invalid password', as_error=True)
|
||||
return types.auth.FAILED_AUTH
|
||||
|
||||
# store the user mfa attribute if it is set
|
||||
|
@ -368,14 +368,14 @@ class SimpleLDAPAuthenticator(auths.Authenticator):
|
||||
user = self._get_user(username)
|
||||
|
||||
if user is None:
|
||||
log_login(request, self.db_obj(), username, 'Invalid user')
|
||||
log_login(request, self.db_obj(), username, 'Invalid user', as_error=True)
|
||||
return types.auth.FAILED_AUTH
|
||||
|
||||
try:
|
||||
# Let's see first if it credentials are fine
|
||||
self._connect_as(user['dn'], credentials) # Will raise an exception if it can't connect
|
||||
except Exception:
|
||||
log_login(request, self.db_obj(), username, 'Invalid password')
|
||||
log_login(request, self.db_obj(), username, 'Invalid password', as_error=True)
|
||||
return types.auth.FAILED_AUTH
|
||||
|
||||
# store the user mfa attribute if it is set
|
||||
|
@ -489,6 +489,7 @@ def log_login(
|
||||
authenticator: models.Authenticator,
|
||||
userName: str,
|
||||
log_string: str = '',
|
||||
as_error: bool = False,
|
||||
) -> None:
|
||||
"""
|
||||
Logs authentication
|
||||
@ -496,6 +497,8 @@ def log_login(
|
||||
if log_string == '':
|
||||
log_string = 'Logged in'
|
||||
|
||||
log_level = types.log.LogLevel.ERROR if as_error else types.log.LogLevel.INFO
|
||||
|
||||
authLogger.info(
|
||||
'|'.join(
|
||||
[
|
||||
@ -508,10 +511,9 @@ def log_login(
|
||||
]
|
||||
)
|
||||
)
|
||||
level = types.log.LogLevel.INFO if log_string == 'Logged in' else types.log.LogLevel.ERROR
|
||||
log.log(
|
||||
authenticator,
|
||||
level,
|
||||
log_level,
|
||||
f'user {userName} has {log_string} from {request.ip} where os is {request.os.os.name}',
|
||||
types.log.LogSource.WEB,
|
||||
)
|
||||
@ -521,7 +523,7 @@ def log_login(
|
||||
user = authenticator.users.get(name=userName)
|
||||
log.log(
|
||||
user,
|
||||
level,
|
||||
log_level,
|
||||
f'{log_string} from {request.ip} where OS is {request.os.os.name}',
|
||||
types.log.LogSource.WEB,
|
||||
)
|
||||
|
@ -82,61 +82,63 @@ def check_login( # pylint: disable=too-many-branches, too-many-statements
|
||||
authenticator = Authenticator.objects.get(uuid=process_uuid(form.cleaned_data['authenticator']))
|
||||
except Exception:
|
||||
authenticator = Authenticator.null()
|
||||
userName = form.cleaned_data['user']
|
||||
username = form.cleaned_data['user']
|
||||
if GlobalConfig.LOWERCASE_USERNAME.as_bool(True) is True:
|
||||
userName = userName.lower()
|
||||
username = username.lower()
|
||||
|
||||
cache = Cache('auth')
|
||||
cacheKey = str(authenticator.id) + userName
|
||||
tries = cache.get(cacheKey) or 0
|
||||
triesByIp = (cache.get(request.ip) or 0) if GlobalConfig.LOGIN_BLOCK_IP.as_bool() else 0
|
||||
maxTries = GlobalConfig.MAX_LOGIN_TRIES.as_int()
|
||||
tries_cache_key = str(authenticator.id) + username
|
||||
tries = cache.get(tries_cache_key) or 0
|
||||
tries_in_this_ip = (cache.get(request.ip) or 0) if GlobalConfig.LOGIN_BLOCK_IP.as_bool() else 0
|
||||
max_tries_per_ip = GlobalConfig.MAX_LOGIN_TRIES.as_int()
|
||||
# Get instance..
|
||||
authInstance = authenticator.get_instance()
|
||||
auth_instance = authenticator.get_instance()
|
||||
# Check if user is locked
|
||||
if authInstance.block_user_on_failures is True and (tries >= maxTries) or triesByIp >= maxTries:
|
||||
log_login(request, authenticator, userName, 'Temporarily blocked')
|
||||
if auth_instance.block_user_on_failures is True and (tries >= max_tries_per_ip) or tries_in_this_ip >= max_tries_per_ip:
|
||||
log_login(request, authenticator, username, 'Temporarily blocked', as_error=True)
|
||||
return types.auth.LoginResult(errstr=_('Too many authentication errrors. User temporarily blocked'))
|
||||
# check if authenticator is visible for this requests
|
||||
if authInstance.is_ip_allowed(request=request) is False:
|
||||
if auth_instance.is_ip_allowed(request=request) is False:
|
||||
log_login(
|
||||
request,
|
||||
authenticator,
|
||||
userName,
|
||||
username,
|
||||
'Access tried from an unallowed source',
|
||||
as_error=True,
|
||||
)
|
||||
return types.auth.LoginResult(errstr=_('Access tried from an unallowed source'))
|
||||
|
||||
password = (
|
||||
form.cleaned_data['password'] or 'axd56adhg466jasd6q8sadñ€sáé--v'
|
||||
) # Random string, in fact, just a placeholder that will not be used :)
|
||||
authResult = authenticate(userName, password, authenticator, request=request)
|
||||
logger.debug('User: %s', authResult.user)
|
||||
auth_result = authenticate(username, password, authenticator, request=request)
|
||||
logger.debug('User: %s', auth_result.user)
|
||||
|
||||
if authResult.user is None:
|
||||
logger.debug("Invalid user %s (access denied)", userName)
|
||||
cache.put(cacheKey, tries + 1, GlobalConfig.LOGIN_BLOCK.as_int())
|
||||
cache.put(request.ip, triesByIp + 1, GlobalConfig.LOGIN_BLOCK.as_int())
|
||||
if auth_result.user is None:
|
||||
logger.debug("Invalid user %s (access denied)", username)
|
||||
cache.put(tries_cache_key, tries + 1, GlobalConfig.LOGIN_BLOCK.as_int())
|
||||
cache.put(request.ip, tries_in_this_ip + 1, GlobalConfig.LOGIN_BLOCK.as_int())
|
||||
log_login(
|
||||
request,
|
||||
authenticator,
|
||||
userName,
|
||||
username,
|
||||
'Access denied (user not allowed by UDS)',
|
||||
as_error=True,
|
||||
)
|
||||
if authResult.url: # Redirection
|
||||
return types.auth.LoginResult(url=authResult.url)
|
||||
if auth_result.url: # Redirection
|
||||
return types.auth.LoginResult(url=auth_result.url)
|
||||
return types.auth.LoginResult(errstr=_('Access denied'))
|
||||
|
||||
request.session.cycle_key()
|
||||
|
||||
logger.debug('User %s has logged in', userName)
|
||||
cache.remove(cacheKey) # Valid login, remove cached tries
|
||||
logger.debug('User %s has logged in', username)
|
||||
cache.remove(tries_cache_key) # Valid login, remove cached tries
|
||||
|
||||
if form.cleaned_data['logouturl'] != '':
|
||||
logger.debug('The logoout url will be %s', form.cleaned_data['logouturl'])
|
||||
request.session['logouturl'] = form.cleaned_data['logouturl']
|
||||
log_login(request, authenticator, authResult.user.name)
|
||||
return types.auth.LoginResult(user=authResult.user, password=form.cleaned_data['password'])
|
||||
log_login(request, authenticator, auth_result.user.name)
|
||||
return types.auth.LoginResult(user=auth_result.user, password=form.cleaned_data['password'])
|
||||
|
||||
logger.info('Invalid form received')
|
||||
return types.auth.LoginResult(errstr=_('Invalid data'))
|
||||
|
@ -107,14 +107,14 @@ def auth_callback_stage2(request: 'ExtendedHttpRequestWithUser', ticket_id: str)
|
||||
raise exceptions.auth.Redirect(result.url)
|
||||
|
||||
if result.user is None:
|
||||
log_login(request, authenticator, f'{params}', 'Invalid at auth callback')
|
||||
log_login(request, authenticator, f'{params}', 'Invalid at auth callback', as_error=True)
|
||||
raise exceptions.auth.InvalidUserException()
|
||||
|
||||
response = HttpResponseRedirect(reverse('page.index'))
|
||||
|
||||
web_login(request, response, result.user, '') # Password is unavailable in this case
|
||||
|
||||
log_login(request, authenticator, result.user.name, 'Federated login')
|
||||
log_login(request, authenticator, result.user.name, 'Federated login') # Nice login, just indicating it's federated
|
||||
|
||||
# If MFA is provided, we need to redirect to MFA page
|
||||
request.authorized = True
|
||||
@ -237,7 +237,7 @@ def ticket_auth(
|
||||
web_login(request, None, usr, password)
|
||||
|
||||
# Log the login
|
||||
log_login(request, auth, username, 'Ticket authentication')
|
||||
log_login(request, auth, username, 'Ticket authentication') # Nice login, just indicating it's using a ticket
|
||||
|
||||
request.user = (
|
||||
usr # Temporarily store this user as "authenticated" user, next requests will be done using session
|
||||
|
Loading…
Reference in New Issue
Block a user