core: improve error template (#3521)

This commit is contained in:
Jens L 2022-09-03 19:46:37 +02:00 committed by GitHub
parent 242423cf3c
commit f2f22719f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 45 additions and 44 deletions

View File

@ -1,31 +0,0 @@
{% extends 'base/skeleton.html' %}
{% load i18n %}
{% block head %}
{{ block.super }}
<style>
.pf-c-empty-state {
height: 100vh;
}
</style>
{% endblock %}
{% block body %}
<section class="ak-static-page pf-c-page__main-section pf-m-no-padding-mobile pf-m-xl">
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<i class="fas fa-exclamation-circle pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">
{% trans title %}
</h1>
<div class="pf-c-empty-state__body">
{% if message %}
<h3>{% trans message %}</h3>
{% endif %}
</div>
<a href="/" class="pf-c-button pf-m-primary pf-m-block">{% trans 'Go to home' %}</a>
</div>
</div>
</section>
{% endblock %}

View File

@ -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 %}
<form method="POST" class="pf-c-form">
<p>{% trans message %}</p>
<a id="ak-back-home" href="{% url 'authentik_core:root-redirect' %}" class="pf-c-button pf-m-primary">
{% trans 'Go home' %}
</a>
</form>
{% endblock %}

View File

@ -32,7 +32,7 @@ class BadRequestView(TemplateView):
extra_context = {"title": "Bad Request"} extra_context = {"title": "Bad Request"}
response_class = BadRequestTemplateResponse response_class = BadRequestTemplateResponse
template_name = "error/generic.html" template_name = "if/error.html"
class ForbiddenView(TemplateView): class ForbiddenView(TemplateView):
@ -41,7 +41,7 @@ class ForbiddenView(TemplateView):
extra_context = {"title": "Forbidden"} extra_context = {"title": "Forbidden"}
response_class = ForbiddenTemplateResponse response_class = ForbiddenTemplateResponse
template_name = "error/generic.html" template_name = "if/error.html"
class NotFoundView(TemplateView): class NotFoundView(TemplateView):
@ -50,7 +50,7 @@ class NotFoundView(TemplateView):
extra_context = {"title": "Not Found"} extra_context = {"title": "Not Found"}
response_class = NotFoundTemplateResponse response_class = NotFoundTemplateResponse
template_name = "error/generic.html" template_name = "if/error.html"
class ServerErrorView(TemplateView): class ServerErrorView(TemplateView):
@ -59,7 +59,7 @@ class ServerErrorView(TemplateView):
extra_context = {"title": "Server Error"} extra_context = {"title": "Server Error"}
response_class = ServerErrorTemplateResponse response_class = ServerErrorTemplateResponse
template_name = "error/generic.html" template_name = "if/error.html"
# pylint: disable=useless-super-delegation # pylint: disable=useless-super-delegation
def dispatch(self, *args, **kwargs): # pragma: no cover def dispatch(self, *args, **kwargs): # pragma: no cover

View File

@ -8,7 +8,7 @@ def bad_request_message(
request: HttpRequest, request: HttpRequest,
message: str, message: str,
title="Bad Request", title="Bad Request",
template="error/generic.html", template="if/error.html",
) -> TemplateResponse: ) -> TemplateResponse:
"""Return generic error page with message, with status code set to 400""" """Return generic error page with message, with status code set to 400"""
return TemplateResponse( return TemplateResponse(

View File

@ -1,9 +1,12 @@
"""OAuth errors""" """OAuth errors"""
from typing import Optional 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.events.models import Event, EventAction
from authentik.lib.sentry import SentryIgnoredException from authentik.lib.sentry import SentryIgnoredException
from authentik.lib.views import bad_request_message
from authentik.providers.oauth2.models import GrantTypes from authentik.providers.oauth2.models import GrantTypes
@ -150,6 +153,14 @@ class AuthorizeError(OAuth2Error):
self.grant_type = grant_type self.grant_type = grant_type
self.state = state 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: def create_uri(self) -> str:
"""Get a redirect URI with the error message""" """Get a redirect URI with the error message"""
description = quote(str(self.description)) description = quote(str(self.description))

View File

@ -8,7 +8,7 @@ from urllib.parse import parse_qs, urlencode, urlparse, urlsplit, urlunsplit
from uuid import uuid4 from uuid import uuid4
from django.http import HttpRequest, HttpResponse 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.shortcuts import get_object_or_404
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
@ -284,7 +284,7 @@ class AuthorizationFlowInitView(PolicyAccessView):
self.params = OAuthAuthorizationParams.from_request(self.request) self.params = OAuthAuthorizationParams.from_request(self.request)
except AuthorizeError as error: except AuthorizeError as error:
LOGGER.warning(error.description, redirect_uri=error.redirect_uri) 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: except OAuth2Error as error:
LOGGER.warning(error.description) LOGGER.warning(error.description)
raise RequestValidationError( raise RequestValidationError(
@ -301,7 +301,7 @@ class AuthorizationFlowInitView(PolicyAccessView):
self.params.state, self.params.state,
) )
error.to_event(redirect_uri=error.redirect_uri).from_http(self.request) 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): def resolve_provider_application(self):
client_id = self.request.GET.get("client_id") client_id = self.request.GET.get("client_id")
@ -463,7 +463,7 @@ class OAuthFulfillmentStage(StageView):
except AuthorizeError as error: except AuthorizeError as error:
error.to_event(application=self.application).from_http(request) error.to_event(application=self.application).from_http(request)
self.executor.stage_invalid() self.executor.stage_invalid()
return self.redirect(error.create_uri()) return error.get_response(self.request)
def create_response_uri(self) -> str: def create_response_uri(self) -> str:
"""Create a final Response URI the user is redirected to.""" """Create a final Response URI the user is redirected to."""

View File

@ -91,7 +91,7 @@ class SAMLSSOBindingRedirectView(SAMLSSOView):
def check_saml_request(self) -> Optional[HttpRequest]: def check_saml_request(self) -> Optional[HttpRequest]:
"""Handle REDIRECT bindings""" """Handle REDIRECT bindings"""
if REQUEST_KEY_SAML_REQUEST not in self.request.GET: 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.") return bad_request_message(self.request, "The SAML request payload is missing.")
try: try:
@ -127,7 +127,7 @@ class SAMLSSOBindingPOSTView(SAMLSSOView):
if SESSION_KEY_POST in self.request.session: if SESSION_KEY_POST in self.request.session:
payload = self.request.session.pop(SESSION_KEY_POST) payload = self.request.session.pop(SESSION_KEY_POST)
if REQUEST_KEY_SAML_REQUEST not in payload: 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.") return bad_request_message(self.request, "The SAML request payload is missing.")
try: try:
@ -147,6 +147,6 @@ class SAMLSSOBindingInitView(SAMLSSOView):
def check_saml_request(self) -> Optional[HttpRequest]: def check_saml_request(self) -> Optional[HttpRequest]:
"""Create SAML Response from scratch""" """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() auth_n_request = AuthNRequestParser(self.provider).idp_initiated()
self.request.session[SESSION_KEY_AUTH_N_REQUEST] = auth_n_request self.request.session[SESSION_KEY_AUTH_N_REQUEST] = auth_n_request