1
0
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:
Adolfo Gómez García 2024-09-16 16:22:42 +02:00
parent c67eee8b73
commit c7666bb4f2
No known key found for this signature in database
GPG Key ID: DD1ABF20724CDA23
7 changed files with 41 additions and 36 deletions

View File

@ -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:

View File

@ -168,6 +168,7 @@ class RadiusAuth(auths.Authenticator):
self.db_obj(),
username,
'Access denied by Raiuds',
as_error=True,
)
return types.auth.FAILED_AUTH

View File

@ -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

View File

@ -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

View File

@ -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,
)

View File

@ -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'))

View File

@ -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