core: improve error template (#3521)
This commit is contained in:
parent
242423cf3c
commit
f2f22719f8
|
@ -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 %}
|
|
|
@ -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 %}
|
|
@ -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
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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."""
|
||||||
|
|
|
@ -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
|
||||||
|
|
Reference in New Issue