diff --git a/portal/views/logon.py b/portal/views/logon.py
index 1c1dc88..da7e8e6 100644
--- a/portal/views/logon.py
+++ b/portal/views/logon.py
@@ -36,7 +36,7 @@
# Django project imports
from gui.models.application_settings import Application
from gui.models.system_settings import Cluster
-from portal.views.responses import response_redirect_with_portal_cookie, set_portal_cookie
+from portal.views.responses import response_redirect_with_portal_cookie, set_portal_cookie, response_success, response_failure
from portal.system.authentications import Authentication, POSTAuthentication, BASICAuthentication, KERBEROSAuthentication, DOUBLEAuthentication
from portal.system.sso_forwards import SSOForwardPOST, SSOForwardBASIC, SSOForwardKERBEROS
@@ -63,14 +63,14 @@
logger = logging.getLogger('portal_authentication')
-
-
def log_in(request, token_name=None, token=None, proxy_app_id=None):
""" Handle authentication in Vulture Portal
:param request: Django request object
:returns: Home page if user auth succeed. Logon page if auth failed
"""
+ default_authentication_type = None
+
cluster = Cluster.objects.get()
""" Check if URI arguments are valid """
if token_name and token_name != cluster.getTokenName():
@@ -99,7 +99,7 @@ def log_in(request, token_name=None, token=None, proxy_app_id=None):
# Redis connection error
except RedisConnectionError as e:
logger.error("PORTAL::log_in: Unable to connect to Redis server : {}".format(str(e)))
- return HttpResponseServerError()
+ return response_failure(HttpResponseServerError(), "authentication")
# Token not found while instantiating RedisSession or RedisAppSession
except TokenNotFoundError as e:
@@ -112,12 +112,12 @@ def log_in(request, token_name=None, token=None, proxy_app_id=None):
# If "proxy_app_id" not found : FORBIDDEN
except (Application.DoesNotExist, InvalidId, ValidationError) as e:
logger.error("PORTAL::log_in: Application with id '{}' not found : {}".format(proxy_app_id, str(e)))
- return HttpResponseForbidden()
+ return response_failure(HttpResponseForbidden(), "authentication")
# If redis_session.keys['application_id'] does not exists : FORBIDDEN
except (Application.DoesNotExist, ValidationError, InvalidId) as e:
logger.error("PORTAL::log_in: Application with id '{}' not found".format(authentication.redis_session.keys['application_id']))
- return HttpResponseForbidden()
+ return response_failure(HttpResponseForbidden(), "authentication")
# If assertionError : Ask credentials by portal
except AssertionError as e:
@@ -128,6 +128,7 @@ def log_in(request, token_name=None, token=None, proxy_app_id=None):
""" If user is not authenticated : try to retrieve credentials and authenticate him on backend/fallback-backends """
# If the user is not authenticated and application need authentication
if not authentication.is_authenticated():
+ default_authentication_type = "authentication"
try:
backend_id = authentication.authenticate_on_backend()
if not backend_id:
@@ -146,7 +147,7 @@ def log_in(request, token_name=None, token=None, proxy_app_id=None):
if authentication_results['data'].get('password_expired', None):
logger.info("PORTAL::log_in: User '{}' must change its password, redirect to self-service portal".format(authentication.credentials[0]))
app_url = authentication.get_url_portal()
- return response_redirect_with_portal_cookie(app_url+str(token_name)+'/self/change', portal_cookie_name, portal_cookie, app_url.startswith('https'), None)
+ return response_success(response_redirect_with_portal_cookie(app_url+str(token_name)+'/self/change', portal_cookie_name, portal_cookie, app_url.startswith('https'), None), "authentication")
# If the user is already authenticated (retrieven with RedisPortalSession ) => SSO
else:
app_cookie, portal_cookie, oauth2_token = authentication.register_sso(backend_id)
@@ -154,23 +155,23 @@ def log_in(request, token_name=None, token=None, proxy_app_id=None):
except AssertionError as e:
logger.error("PORTAL::log_in: Bad captcha taped for username '{}' : {}".format(authentication.credentials[0], e))
- return authentication.ask_credentials_response(request=request, error="Bad captcha")
+ return response_failure(authentication.ask_credentials_response(request=request, error="Bad captcha"), "authentication")
except AccountLocked as e:
logger.error("PORTAL::log_in: Error while trying to authenticate user '{}' : {}".format(authentication.credentials[0], e))
- return authentication.ask_credentials_response(request=request, error="Bad credentials")
+ return response_failure(authentication.ask_credentials_response(request=request, error="Bad credentials"), "authentication")
except AuthenticationError as e:
logger.error("PORTAL::log_in: AuthenticationError while trying to authenticate user '{}' : {}".format(authentication.credentials[0], e))
- return authentication.ask_credentials_response(request=request, error="Bad credentials")
+ return response_failure(authentication.ask_credentials_response(request=request, error="Bad credentials"), "authentication")
except ACLError as e:
logger.error("PORTAL::log_in: ACLError while trying to authenticate user '{}' : {}".format(authentication.credentials[0], e))
- return authentication.ask_credentials_response(request=request, error="Bad credentials")
+ return response_failure(authentication.ask_credentials_response(request=request, error="Bad credentials"), "authentication")
except (DBAPIError, PyMongoError, LDAPError) as e:
logger.error("PORTAL::log_in: Repository driver Error while trying to authentication user '{}' : {}".format(authentication.credentials[0], e))
- return authentication.ask_credentials_response(request=request, error="Bad credentials")
+ return response_failure(authentication.ask_credentials_response(request=request, error="Bad credentials"), "authentication")
except (MultiValueDictKeyError, AttributeError, KeyError) as e:
#vltprtlsrnm is always empty during the initial redirection. Don't log that
@@ -179,16 +180,17 @@ def log_in(request, token_name=None, token=None, proxy_app_id=None):
except REDISWriteError as e:
logger.error("PORTAL::log_in: RedisWriteError while trying to register user '{}' informations : {}".format(authentication.credentials[0], e))
- return HttpResponseServerError()
+ return response_failure(HttpResponseServerError(), "authentication")
except Exception as e:
logger.exception(e)
- return HttpResponseServerError()
+ return response_failure(HttpResponseServerError(), "authentication")
""" If user is not double-authenticated and double-authentication needed : try to retrieve credentials and authenticate him on otp-backend """
# If the user is authenticated but not double-authenticated and double-authentication required
if authentication.double_authentication_required():
+ default_authentication_type = "otp"
logger.info("PORTAL::log_in: Double authentication required for user '{}'".format(authentication.credentials[0]))
try:
# Instantiate DOUBLEAuthentication object
@@ -204,17 +206,17 @@ def log_in(request, token_name=None, token=None, proxy_app_id=None):
except AssertionError as e:
""" If redis_portal_session does not exists or can't retrieve otp key in redis """
logger.error("PORTAL::log_in: DoubleAuthentication failure for username '{}' : {}".format(authentication.credentials[0], str(e)))
- return authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name, error="Portal cookie expired")
+ return response_failure(authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name, error="Portal cookie expired"), "otp")
except (Application.DoesNotExist, ValidationError, InvalidId) as e:
""" Invalid POST 'vulture_two_factors_authentication' value """
logger.error("PORTAL::log_in: Double-authentication failure for username {} : {}".format(authentication.credentials[0], str(e)))
- return HttpResponseForbidden("Intrusion attempt blocked")
+ return response_failure(HttpResponseForbidden("Intrusion attempt blocked"), "otp")
except REDISWriteError as e:
""" Cannot register double-authentication in Redis : internal server error """
logger.error("PORTAL::log_in: Failed to write double-authentication results in Redis for username '{}' : {}".format(db_authentication.credentials[0], str(e)))
- return HttpResponseServerError()
+ return response_failure(HttpResponseServerError(), "otp")
# If authentication failed : create double-authentication key and ask-it
except CredentialsError as e:
@@ -222,14 +224,15 @@ def log_in(request, token_name=None, token=None, proxy_app_id=None):
logger.error("PORTAL::log_in: Double-authentication failure for username {} : {}".format(authentication.credentials[0], str(e)))
try:
db_authentication.create_authentication()
- return db_authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name)
+ # If we get here, authentication has succeed
+ return response_success(db_authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name), "authentication")
except (OTPError, REDISWriteError, RedisConnectionError) as e:
""" Error while sending/registering in Redis the OTP informations : display portal"""
logger.error("PORTAL::log_in: Failed to create/send double-authentication key : {}".format(str(e)))
db_authentication.deauthenticate_user()
logger.info("PORTAL::log_in: User '{}' successfully deauthenticated due to db-authentication error".format(authentication.credentials[0]))
- return authentication.ask_credentials_response(request=request, error=" Error sending OTP Key "+str(e))
+ return response_failure(authentication.ask_credentials_response(request=request, error=" Error sending OTP Key "+str(e)), "otp")
except AuthenticationError as e:
""" Bad OTP key """
@@ -238,29 +241,29 @@ def log_in(request, token_name=None, token=None, proxy_app_id=None):
db_authentication.create_authentication()
db_authentication.authentication_failure()
logger.debug("PORTAL:log_in: DoubleAuthentication failure successfully registered in Redis")
- return db_authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name, error=" Bad OTP key ")
+ return response_failure(db_authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name, error=" Bad OTP key "), "otp")
except TwoManyOTPAuthFailure as e:
logger.error("PORTAL::log_in: Two many OTP authentication failures for username'{}', redirecting to portal".format(authentication.credentials[0]))
db_authentication.deauthenticate_user()
logger.info("PORTAL::log_in: User '{}' successfully deauthenticated due to db-authentication error".format(authentication.credentials[0]))
- return authentication.ask_credentials_response(request=request, error=e.args[0])
+ return response_failure(authentication.ask_credentials_response(request=request, error=e.args[0]), "otp")
except (OTPError, REDISWriteError, RedisConnectionError) as e:
logger.error("PORTAL::log_in: Error while preparing double-authentication : {}".format(str(e)))
- return db_authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name, error=" Error sending OTP Key "+str(e))
+ return response_failure(db_authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name, error=" Error sending OTP Key "+str(e)), "otp")
except OTPError as e:
""" OTP Error while authenticating given token """
logger.error("PORTAL::log_in: Double-authentication failure for username {} : {}".format(authentication.credentials[0], str(e)))
- return db_authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name, error=" OTP Error {}".format(str(e)))
+ return response_failure(db_authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name, error=" OTP Error {}".format(str(e))), "otp")
except TwoManyOTPAuthFailure as e:
logger.error(
"PORTAL::log_in: Two many OTP authentication failures for username'{}', redirecting to portal".format(authentication.credentials[0]))
db_authentication.deauthenticate_user()
logger.info("PORTAL::log_in: User '{}' successfully deauthenticated due to db-authentication error".format(authentication.credentials[0]))
- return authentication.ask_credentials_response(request=request, error=e.args[0])
+ return response_failure(authentication.ask_credentials_response(request=request, error=e.args[0]), "otp")
# If we arrive here : the user is authenticated
# and double-authenticated if double-authentication needed
@@ -278,13 +281,14 @@ def log_in(request, token_name=None, token=None, proxy_app_id=None):
authentication.get_credentials(request)
# If we cannot retrieve them, ask credentials
if not authentication.credentials[0]:# or not authentication.credentials[1]:
- return authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name, error="Credentials not found")
+ # If we get here, otp or auth has succeed
+ return response_success(authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name, error="Credentials not found"), default_authentication_type)
logger.info("PORTAL::log_in: Credentials successfuly retrieven for SSO performing")
except Exception as e:
logger.error("PORTAL::log_in: Error while retrieving credentials for SSO : ")
logger.exception(e)
- return authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name, error="Credentials not found")
+ return response_success(authentication.ask_credentials_response(request=request, portal_cookie_name=portal_cookie_name, error="Credentials not found"), default_authentication_type)
try:
# Instantiate SSOForward object with sso_forward type
@@ -307,12 +311,12 @@ def log_in(request, token_name=None, token=None, proxy_app_id=None):
# If the user has not yet a portal cookie : give-it
if not request.COOKIES.get(portal_cookie_name, None) or not authentication.redis_base.hgetall(request.COOKIES.get(portal_cookie_name, None)):
final_response = set_portal_cookie(final_response, portal_cookie_name, portal_cookie, authentication.get_redirect_url())
- return final_response
+ return response_success(final_response, default_authentication_type)
# If learning credentials cannot be retrieven : ask them
except CredentialsMissingError as e:
logger.error("PORTAL::log_in: Learning credentials missing : asking-them")
- return authentication.ask_learning_credentials(request=request, portal_cookie_name=None if request.POST.get(portal_cookie_name, None) else portal_cookie_name, fields=e.fields_missing)
+ return response_success(authentication.ask_learning_credentials(request=request, portal_cookie_name=None if request.POST.get(portal_cookie_name, None) else portal_cookie_name, fields=e.fields_missing), default_authentication_type)
# If KerberosBackend object cannot be retrieven from mongo with the backend_id that the user is authenticated on
except InvalidId:
@@ -334,5 +338,5 @@ def log_in(request, token_name=None, token=None, proxy_app_id=None):
kerberos_token_resp = authentication_results['data']['token_resp']
except:
kerberos_token_resp = None
- return response_redirect_with_portal_cookie(redirection_url, portal_cookie_name, portal_cookie, redirection_url.startswith('https'), kerberos_token_resp)
+ return response_success(response_redirect_with_portal_cookie(redirection_url, portal_cookie_name, portal_cookie, redirection_url.startswith('https'), kerberos_token_resp), default_authentication_type)
diff --git a/portal/views/oauth2_portal.py b/portal/views/oauth2_portal.py
index 2cdd437..92acdf0 100644
--- a/portal/views/oauth2_portal.py
+++ b/portal/views/oauth2_portal.py
@@ -34,6 +34,7 @@
from gui.models.system_settings import Cluster
from portal.system.authentications import OAUTH2Authentication
from portal.system.redis_sessions import REDISBase
+from portal.views.responses import response_success, response_failure
# Required exceptions imports
from bson.errors import InvalidId
@@ -80,7 +81,7 @@ def log_in(request):
logger.info("OAUTH2::log_in: Authentication succeed for user '{}'".format(authentication.credentials[0]))
response = authentication.generate_response(authentication_results)
logger.info("OAUTH2::log_in: Response successfully generated for user '{}' : {}".format(authentication.credentials[0], response))
- return response
+ return response_success(response, "oauth2")
# Redis connection error
except RedisConnectionError as e:
@@ -109,7 +110,7 @@ def log_in(request):
logger.error("OAUTH2::log_in: Error while trying to authentication user '{}' : ".format(request.POST.get('username',None)))
logger.exception(e)
- return HttpResponseForbidden()
+ return response_failure(HttpResponseForbidden(), "oauth2")
@@ -162,6 +163,7 @@ def is_valid_token(request):
body = {"active": "false"}
logger.debug("OAuth2Portal::is_valid_token: Returning '{}'".format(body))
+ response_funcs = {"true"}
return JsonResponse(body)
else:
diff --git a/portal/views/responses.py b/portal/views/responses.py
index 988c4cb..f31f39a 100644
--- a/portal/views/responses.py
+++ b/portal/views/responses.py
@@ -41,6 +41,22 @@
# Global variables
BASE_DIR = dirname(dirname(__file__))
+AUTH_TYPE_HEADER = "X-Authentication"
+AUTH_RESULT_HEADER = "X-Authentication-Result"
+
+
+def response_success(response, action_type):
+ if action_type:
+ response[AUTH_TYPE_HEADER] = action_type
+ response[AUTH_RESULT_HEADER] = "success"
+ return response
+
+def response_failure(response, action_type):
+ if action_type:
+ response[AUTH_TYPE_HEADER] = action_type
+ response[AUTH_RESULT_HEADER] = "failure"
+ return response
+
def split_domain(url):
""" Split an url and return the 2 last domains
diff --git a/portal/views/self.py b/portal/views/self.py
index 4316b1a..d8797ab 100644
--- a/portal/views/self.py
+++ b/portal/views/self.py
@@ -36,6 +36,7 @@
# Django project imports
from portal.system.self_actions import SELFService, SELFServiceChange, SELFServiceLogout, SELFServiceLost
from vulture_toolkit.auth.exceptions import AuthenticationError, ChangePasswordError
+from portal.views.responses import response_failure, response_success
# Required exceptions imports
from django.utils.datastructures import MultiValueDictKeyError
@@ -81,17 +82,17 @@ def self(request, token_name=None, proxy_app_id=None, action=None):
except RedisConnectionError as e:
# Redis connection error
logger.error("PORTAL::log_in: Unable to connect to Redis server : {}".format(str(e)))
- return HttpResponseServerError()
+ return response_failure(HttpResponseServerError(),action)
# If assertionError : Forbidden
except AssertionError as e:
logger.error("PORTAL::log_in: AssertionError while trying to create Authentication : ".format(e))
- return HttpResponseForbidden()
+ return response_failure(HttpResponseForbidden(), action)
except Exception as e:
logger.error("Unknown error occured while retrieving user informations :")
logger.exception(e)
- return HttpResponseForbidden()
+ return response_failure(HttpResponseForbidden(), action)
try:
@@ -99,33 +100,33 @@ def self(request, token_name=None, proxy_app_id=None, action=None):
if not action:
result = Action.perform_action()
logger.info("SELF::main: List of apps successfully retrieven")
- return Action.main_response(request, result)
+ return response_success(Action.main_response(request, result), "list_apps")
else:
- return Action.message_response(Action.perform_action(request, credential))
+ return response_success(Action.message_response(Action.perform_action(request, credential)), action)
# Redis connection error
except RedisConnectionError as e:
logger.error("PORTAL::log_in: Unable to connect to Redis server : {}".format(str(e)))
- return HttpResponseServerError()
+ return response_failure(HttpResponseServerError(), action)
# If assertionError : Forbidden
except AssertionError as e:
logger.error("PORTAL::log_in: AssertionError while trying to create Authentication : '{}'".format(e))
- return HttpResponseForbidden(e)
+ return response_failure(HttpResponseForbidden(e), action)
except (DBAPIError, LDAPError, PyMongoError) as e:
logger.error("SELF::self: Failed to update password :".format(e))
logger.exception(e)
- return Action.ask_credentials_response(request, action, " Database error
"
- "Please contact your administrator")
+ return response_failure(Action.ask_credentials_response(request, action, " Database error
"
+ "Please contact your administrator"), action)
except PasswordMatchError as e:
logger.error("SELF::self: Validation form error: '{}'".format(e))
- return Action.ask_credentials_response(request, action, e)
+ return response_failure(Action.ask_credentials_response(request, action, e), action)
except (ChangePasswordError, AuthenticationError) as e:
logger.error("SELF::self: Authentication or credentials error : '{}'".format(e))
- return Action.ask_credentials_response(request, action, "Authentication failure.")
+ return response_failure(Action.ask_credentials_response(request, action, "Authentication failure."), action)
except MultiValueDictKeyError as e:
if request.method == "GET":
@@ -135,13 +136,13 @@ def self(request, token_name=None, proxy_app_id=None, action=None):
return Action.ask_credentials_response(request, action, "Field missing : "+str(e))
except SMTPException as e:
- return Action.ask_credentials_response(request, action, str(e))
+ return response_failure(Action.ask_credentials_response(request, action, str(e)), action)
except KeyError as e:
logger.exception(e)
- return HttpResponseForbidden()
+ return response_failure(HttpResponseForbidden(), action)
except Exception as e:
logger.error(type(e))
logger.exception(e)
- return Action.message_response("An unknown error occured
Please contact your admninistrator")
+ return response_failure(Action.message_response("An unknown error occured
Please contact your admninistrator"), action)