diff --git a/authentik/core/templates/error/generic.html b/authentik/core/templates/error/generic.html deleted file mode 100644 index 4868f79d8..000000000 --- a/authentik/core/templates/error/generic.html +++ /dev/null @@ -1,31 +0,0 @@ -{% extends 'base/skeleton.html' %} - -{% load i18n %} - -{% block head %} -{{ block.super }} - -{% endblock %} - -{% block body %} -
-
-
- -

- {% trans title %} -

-
- {% if message %} -

{% trans message %}

- {% endif %} -
- {% trans 'Go to home' %} -
-
-
-{% endblock %} diff --git a/authentik/core/templates/if/error.html b/authentik/core/templates/if/error.html new file mode 100644 index 000000000..36aaa8860 --- /dev/null +++ b/authentik/core/templates/if/error.html @@ -0,0 +1,21 @@ +{% extends 'login/base_full.html' %} + +{% load static %} +{% load i18n %} + +{% block title %} +{% trans 'End session' %} - {{ tenant.branding_title }} +{% endblock %} + +{% block card_title %} +{% trans title %} +{% endblock %} + +{% block card %} +
+

{% trans message %}

+ + {% trans 'Go home' %} + +
+{% endblock %} diff --git a/authentik/core/views/error.py b/authentik/core/views/error.py index 9f9e4deae..51868d997 100644 --- a/authentik/core/views/error.py +++ b/authentik/core/views/error.py @@ -32,7 +32,7 @@ class BadRequestView(TemplateView): extra_context = {"title": "Bad Request"} response_class = BadRequestTemplateResponse - template_name = "error/generic.html" + template_name = "if/error.html" class ForbiddenView(TemplateView): @@ -41,7 +41,7 @@ class ForbiddenView(TemplateView): extra_context = {"title": "Forbidden"} response_class = ForbiddenTemplateResponse - template_name = "error/generic.html" + template_name = "if/error.html" class NotFoundView(TemplateView): @@ -50,7 +50,7 @@ class NotFoundView(TemplateView): extra_context = {"title": "Not Found"} response_class = NotFoundTemplateResponse - template_name = "error/generic.html" + template_name = "if/error.html" class ServerErrorView(TemplateView): @@ -59,7 +59,7 @@ class ServerErrorView(TemplateView): extra_context = {"title": "Server Error"} response_class = ServerErrorTemplateResponse - template_name = "error/generic.html" + template_name = "if/error.html" # pylint: disable=useless-super-delegation def dispatch(self, *args, **kwargs): # pragma: no cover diff --git a/authentik/lib/views.py b/authentik/lib/views.py index f444dd2d6..f430b149a 100644 --- a/authentik/lib/views.py +++ b/authentik/lib/views.py @@ -8,7 +8,7 @@ def bad_request_message( request: HttpRequest, message: str, title="Bad Request", - template="error/generic.html", + template="if/error.html", ) -> TemplateResponse: """Return generic error page with message, with status code set to 400""" return TemplateResponse( diff --git a/authentik/providers/oauth2/errors.py b/authentik/providers/oauth2/errors.py index c1279b008..8d1f028fc 100644 --- a/authentik/providers/oauth2/errors.py +++ b/authentik/providers/oauth2/errors.py @@ -1,9 +1,12 @@ """OAuth errors""" from typing import Optional -from urllib.parse import quote +from urllib.parse import quote, urlparse + +from django.http import HttpRequest, HttpResponse, HttpResponseRedirect from authentik.events.models import Event, EventAction from authentik.lib.sentry import SentryIgnoredException +from authentik.lib.views import bad_request_message from authentik.providers.oauth2.models import GrantTypes @@ -150,6 +153,14 @@ class AuthorizeError(OAuth2Error): self.grant_type = grant_type self.state = state + def get_response(self, request: HttpRequest) -> HttpResponse: + """Wrapper around `self.create_uri()` that checks if the resulting URI is valid + (we might not have self.redirect_uri set), and returns a valid HTTP Response""" + uri = self.create_uri() + if urlparse(uri).scheme != "": + return HttpResponseRedirect(uri) + return bad_request_message(request, self.description, title=self.error) + def create_uri(self) -> str: """Get a redirect URI with the error message""" description = quote(str(self.description)) diff --git a/authentik/providers/oauth2/views/authorize.py b/authentik/providers/oauth2/views/authorize.py index baf9e1b31..e9f85c3a5 100644 --- a/authentik/providers/oauth2/views/authorize.py +++ b/authentik/providers/oauth2/views/authorize.py @@ -8,7 +8,7 @@ from urllib.parse import parse_qs, urlencode, urlparse, urlsplit, urlunsplit from uuid import uuid4 from django.http import HttpRequest, HttpResponse -from django.http.response import Http404, HttpResponseBadRequest, HttpResponseRedirect +from django.http.response import Http404, HttpResponseBadRequest from django.shortcuts import get_object_or_404 from django.utils import timezone from django.utils.translation import gettext as _ @@ -284,7 +284,7 @@ class AuthorizationFlowInitView(PolicyAccessView): self.params = OAuthAuthorizationParams.from_request(self.request) except AuthorizeError as error: LOGGER.warning(error.description, redirect_uri=error.redirect_uri) - raise RequestValidationError(HttpResponseRedirect(error.create_uri())) + raise RequestValidationError(error.get_response(self.request)) except OAuth2Error as error: LOGGER.warning(error.description) raise RequestValidationError( @@ -301,7 +301,7 @@ class AuthorizationFlowInitView(PolicyAccessView): self.params.state, ) error.to_event(redirect_uri=error.redirect_uri).from_http(self.request) - raise RequestValidationError(HttpResponseRedirect(error.create_uri())) + raise RequestValidationError(error.get_response(self.request)) def resolve_provider_application(self): client_id = self.request.GET.get("client_id") @@ -463,7 +463,7 @@ class OAuthFulfillmentStage(StageView): except AuthorizeError as error: error.to_event(application=self.application).from_http(request) self.executor.stage_invalid() - return self.redirect(error.create_uri()) + return error.get_response(self.request) def create_response_uri(self) -> str: """Create a final Response URI the user is redirected to.""" diff --git a/authentik/providers/saml/views/sso.py b/authentik/providers/saml/views/sso.py index 6cb02bbe9..e44b7c676 100644 --- a/authentik/providers/saml/views/sso.py +++ b/authentik/providers/saml/views/sso.py @@ -91,7 +91,7 @@ class SAMLSSOBindingRedirectView(SAMLSSOView): def check_saml_request(self) -> Optional[HttpRequest]: """Handle REDIRECT bindings""" if REQUEST_KEY_SAML_REQUEST not in self.request.GET: - LOGGER.info("handle_saml_request: SAML payload missing") + LOGGER.info("SAML payload missing") return bad_request_message(self.request, "The SAML request payload is missing.") try: @@ -127,7 +127,7 @@ class SAMLSSOBindingPOSTView(SAMLSSOView): if SESSION_KEY_POST in self.request.session: payload = self.request.session.pop(SESSION_KEY_POST) if REQUEST_KEY_SAML_REQUEST not in payload: - LOGGER.info("check_saml_request: SAML payload missing") + LOGGER.info("SAML payload missing") return bad_request_message(self.request, "The SAML request payload is missing.") try: @@ -147,6 +147,6 @@ class SAMLSSOBindingInitView(SAMLSSOView): def check_saml_request(self) -> Optional[HttpRequest]: """Create SAML Response from scratch""" - LOGGER.debug("handle_saml_no_request: No SAML Request, using IdP-initiated flow.") + LOGGER.debug("No SAML Request, using IdP-initiated flow.") auth_n_request = AuthNRequestParser(self.provider).idp_initiated() self.request.session[SESSION_KEY_AUTH_N_REQUEST] = auth_n_request