From 8a715dd6b55b3be94e2fb5954b9fcc168ccaa11f Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Mon, 3 Nov 2025 11:46:45 +0100 Subject: [PATCH 1/5] :tada: Make social auth exceptions configurable --- dojo/middleware.py | 8 ++++---- dojo/settings/settings.dist.py | 11 +++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/dojo/middleware.py b/dojo/middleware.py index 5b50f3cc987..5adbaf4ef4a 100644 --- a/dojo/middleware.py +++ b/dojo/middleware.py @@ -83,16 +83,16 @@ def __call__(self, request): class CustomSocialAuthExceptionMiddleware(SocialAuthExceptionMiddleware): def process_exception(self, request, exception): if isinstance(exception, requests.exceptions.RequestException): - messages.error(request, "Please use the standard login below.") + messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["SOCIAL_AUTH_EXCEPTION_MESSAGE_REQUEST_EXCEPTION"]) return redirect("/login?force_login_form") if isinstance(exception, AuthCanceled): - messages.warning(request, "Social login was canceled. Please try again or use the standard login.") + messages.warning(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_CANCELED"]) return redirect("/login?force_login_form") if isinstance(exception, AuthFailed): - messages.error(request, "Social login failed. Please try again or use the standard login.") + messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED"]) return redirect("/login?force_login_form") if isinstance(exception, AuthForbidden): - messages.error(request, "You are not authorized to log in via this method. Please contact support or use the standard login.") + messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN"]) return redirect("/login?force_login_form") if isinstance(exception, TypeError) and "'NoneType' object is not iterable" in str(exception): logger.warning("OIDC login error: NoneType is not iterable") diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 9228c8e57fd..584e05cdd30 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -174,6 +174,10 @@ DD_SOCIAL_AUTH_GITHUB_ENTERPRISE_KEY=(str, ""), DD_SOCIAL_AUTH_GITHUB_ENTERPRISE_SECRET=(str, ""), DD_SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL=(bool, True), + DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_REQUEST_EXCEPTION=(str, "Please use the standard login below."), + DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_CANCELED=(str, "Social login was canceled. Please try again or use the standard login."), + DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED=(str, "Social login failed. Please try again or use the standard login."), + DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN=(str, "You are not authorized to log in via this method. Please contact support or use the standard login."), DD_SAML2_ENABLED=(bool, False), # Allows to override default SAML authentication backend. Check https://djangosaml2.readthedocs.io/contents/setup.html#custom-user-attributes-processing DD_SAML2_AUTHENTICATION_BACKENDS=(str, "djangosaml2.backends.Saml2Backend"), @@ -645,6 +649,13 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param if value := env("DD_SOCIAL_AUTH_OIDC_LOGIN_BUTTON_TEXT"): SOCIAL_AUTH_OIDC_LOGIN_BUTTON_TEXT = value +SOCIAL_AUTH_EXCEPTION_MESSAGE = { + "SOCIAL_AUTH_EXCEPTION_MESSAGE_REQUEST_EXCEPTION": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_REQUEST_EXCEPTION"), + "SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_CANCELED": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_CANCELED"), + "SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED"), + "SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN"), + } + AUTH0_OAUTH2_ENABLED = env("DD_SOCIAL_AUTH_AUTH0_OAUTH2_ENABLED") SOCIAL_AUTH_AUTH0_KEY = env("DD_SOCIAL_AUTH_AUTH0_KEY") SOCIAL_AUTH_AUTH0_SECRET = env("DD_SOCIAL_AUTH_AUTH0_SECRET") From 2d1a6044a9190563ef0fcf93422de9b4148bf134 Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Mon, 3 Nov 2025 17:52:48 +0100 Subject: [PATCH 2/5] update --- dojo/middleware.py | 2 +- dojo/settings/settings.dist.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dojo/middleware.py b/dojo/middleware.py index 5adbaf4ef4a..5dfe219c6ec 100644 --- a/dojo/middleware.py +++ b/dojo/middleware.py @@ -96,7 +96,7 @@ def process_exception(self, request, exception): return redirect("/login?force_login_form") if isinstance(exception, TypeError) and "'NoneType' object is not iterable" in str(exception): logger.warning("OIDC login error: NoneType is not iterable") - messages.error(request, "An unexpected error occurred during social login. Please use the standard login.") + messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE"]) return redirect("/login?force_login_form") logger.error(f"Unhandled exception during social login: {exception}") return super().process_exception(request, exception) diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 584e05cdd30..e2e0ac9d571 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -178,6 +178,7 @@ DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_CANCELED=(str, "Social login was canceled. Please try again or use the standard login."), DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED=(str, "Social login failed. Please try again or use the standard login."), DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN=(str, "You are not authorized to log in via this method. Please contact support or use the standard login."), + DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE=(str, "An unexpected error occurred during social login. Please use the standard login."), DD_SAML2_ENABLED=(bool, False), # Allows to override default SAML authentication backend. Check https://djangosaml2.readthedocs.io/contents/setup.html#custom-user-attributes-processing DD_SAML2_AUTHENTICATION_BACKENDS=(str, "djangosaml2.backends.Saml2Backend"), @@ -654,6 +655,7 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param "SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_CANCELED": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_CANCELED"), "SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED"), "SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN"), + "SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE"), } AUTH0_OAUTH2_ENABLED = env("DD_SOCIAL_AUTH_AUTH0_OAUTH2_ENABLED") From 54b91eaf83f9ea23366174eeb72b38a92c2a8cdf Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Mon, 3 Nov 2025 18:09:15 +0100 Subject: [PATCH 3/5] fix --- dojo/middleware.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/middleware.py b/dojo/middleware.py index 5dfe219c6ec..789858051d3 100644 --- a/dojo/middleware.py +++ b/dojo/middleware.py @@ -96,7 +96,7 @@ def process_exception(self, request, exception): return redirect("/login?force_login_form") if isinstance(exception, TypeError) and "'NoneType' object is not iterable" in str(exception): logger.warning("OIDC login error: NoneType is not iterable") - messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE"]) + messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE"]) return redirect("/login?force_login_form") logger.error(f"Unhandled exception during social login: {exception}") return super().process_exception(request, exception) From bfeecddc8500c46f05b65ee495b915a028cdc04c Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Wed, 5 Nov 2025 10:54:48 +0100 Subject: [PATCH 4/5] update --- dojo/middleware.py | 2 +- dojo/settings/settings.dist.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dojo/middleware.py b/dojo/middleware.py index 445e04d45d4..1aa646d472f 100644 --- a/dojo/middleware.py +++ b/dojo/middleware.py @@ -95,7 +95,7 @@ def process_exception(self, request, exception): messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN"]) return redirect("/login?force_login_form") if isinstance(exception, AuthTokenError): - messages.error(request, "Social login failed due to an invalid or expired token. Please try again or use the standard login.") + messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_TOKEN_ERROR"]) return redirect("/login?force_login_form") if isinstance(exception, TypeError) and "'NoneType' object is not iterable" in str(exception): logger.warning("OIDC login error: NoneType is not iterable") diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 3ab49c66ea8..25a689f3578 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -179,6 +179,7 @@ DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED=(str, "Social login failed. Please try again or use the standard login."), DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN=(str, "You are not authorized to log in via this method. Please contact support or use the standard login."), DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE=(str, "An unexpected error occurred during social login. Please use the standard login."), + DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_TOKEN_ERROR=(str, "Social login failed due to an invalid or expired token. Please try again or use the standard login."), DD_SAML2_ENABLED=(bool, False), # Allows to override default SAML authentication backend. Check https://djangosaml2.readthedocs.io/contents/setup.html#custom-user-attributes-processing DD_SAML2_AUTHENTICATION_BACKENDS=(str, "djangosaml2.backends.Saml2Backend"), @@ -660,6 +661,7 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param "SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED"), "SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN"), "SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE"), + "SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_TOKEN_ERROR": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_TOKEN_ERROR"), } AUTH0_OAUTH2_ENABLED = env("DD_SOCIAL_AUTH_AUTH0_OAUTH2_ENABLED") From 2c06e6e841a7ff30d0b272c177b4b8d4a62f0f74 Mon Sep 17 00:00:00 2001 From: Manuel Sommer Date: Sun, 9 Nov 2025 16:04:20 +0100 Subject: [PATCH 5/5] udpate --- dojo/middleware.py | 12 ++++++------ dojo/settings/settings.dist.py | 14 ++++++-------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/dojo/middleware.py b/dojo/middleware.py index 1aa646d472f..8c7cb55d2d3 100644 --- a/dojo/middleware.py +++ b/dojo/middleware.py @@ -83,23 +83,23 @@ def __call__(self, request): class CustomSocialAuthExceptionMiddleware(SocialAuthExceptionMiddleware): def process_exception(self, request, exception): if isinstance(exception, requests.exceptions.RequestException): - messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["SOCIAL_AUTH_EXCEPTION_MESSAGE_REQUEST_EXCEPTION"]) + messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE_REQUEST_EXCEPTION) return redirect("/login?force_login_form") if isinstance(exception, AuthCanceled): - messages.warning(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_CANCELED"]) + messages.warning(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_CANCELED) return redirect("/login?force_login_form") if isinstance(exception, AuthFailed): - messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED"]) + messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED) return redirect("/login?force_login_form") if isinstance(exception, AuthForbidden): - messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN"]) + messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN) return redirect("/login?force_login_form") if isinstance(exception, AuthTokenError): - messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_TOKEN_ERROR"]) + messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_TOKEN_ERROR) return redirect("/login?force_login_form") if isinstance(exception, TypeError) and "'NoneType' object is not iterable" in str(exception): logger.warning("OIDC login error: NoneType is not iterable") - messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE["SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE"]) + messages.error(request, settings.SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE) return redirect("/login?force_login_form") logger.error(f"Unhandled exception during social login: {exception}") return super().process_exception(request, exception) diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 25a689f3578..cbf43596ce1 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -655,14 +655,12 @@ def generate_url(scheme, double_slashes, user, password, host, port, path, param if value := env("DD_SOCIAL_AUTH_OIDC_LOGIN_BUTTON_TEXT"): SOCIAL_AUTH_OIDC_LOGIN_BUTTON_TEXT = value -SOCIAL_AUTH_EXCEPTION_MESSAGE = { - "SOCIAL_AUTH_EXCEPTION_MESSAGE_REQUEST_EXCEPTION": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_REQUEST_EXCEPTION"), - "SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_CANCELED": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_CANCELED"), - "SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED"), - "SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN"), - "SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE"), - "SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_TOKEN_ERROR": env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_TOKEN_ERROR"), - } +SOCIAL_AUTH_EXCEPTION_MESSAGE_REQUEST_EXCEPTION = env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_REQUEST_EXCEPTION") +SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_CANCELED = env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_CANCELED") +SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED = env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FAILED") +SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN = env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_FORBIDDEN") +SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE = env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_NONE_TYPE") +SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_TOKEN_ERROR = env("DD_SOCIAL_AUTH_EXCEPTION_MESSAGE_AUTH_TOKEN_ERROR") AUTH0_OAUTH2_ENABLED = env("DD_SOCIAL_AUTH_AUTH0_OAUTH2_ENABLED") SOCIAL_AUTH_AUTH0_KEY = env("DD_SOCIAL_AUTH_AUTH0_KEY")