diff --git a/e2e/test_provider_oauth2_oidc.py b/e2e/test_provider_oauth2_oidc.py
index d504d9c49..c17addd6c 100644
--- a/e2e/test_provider_oauth2_oidc.py
+++ b/e2e/test_provider_oauth2_oidc.py
@@ -33,6 +33,7 @@ from passbook.providers.oauth2.models import (
 )
 
 LOGGER = get_logger()
+APPLICATION_SLUG = "grafana"
 
 
 @skipUnless(platform.startswith("linux"), "requires local docker")
@@ -69,6 +70,12 @@ class TestProviderOAuth2OIDC(SeleniumTestCase):
                 "GF_AUTH_GENERIC_OAUTH_API_URL": (
                     self.url("passbook_providers_oauth2:userinfo")
                 ),
+                "GF_AUTH_SIGNOUT_REDIRECT_URL": (
+                    self.url(
+                        "passbook_providers_oauth2:end-session",
+                        application_slug=APPLICATION_SLUG,
+                    )
+                ),
                 "GF_LOG_LEVEL": "debug",
             },
         }
@@ -97,7 +104,7 @@ class TestProviderOAuth2OIDC(SeleniumTestCase):
         )
         provider.save()
         Application.objects.create(
-            name="Grafana", slug="grafana", provider=provider,
+            name="Grafana", slug=APPLICATION_SLUG, provider=provider,
         )
 
         self.driver.get("http://localhost:3000")
@@ -137,7 +144,7 @@ class TestProviderOAuth2OIDC(SeleniumTestCase):
         )
         provider.save()
         Application.objects.create(
-            name="Grafana", slug="grafana", provider=provider,
+            name="Grafana", slug=APPLICATION_SLUG, provider=provider,
         )
 
         self.driver.get("http://localhost:3000")
@@ -171,6 +178,72 @@ class TestProviderOAuth2OIDC(SeleniumTestCase):
             USER().email,
         )
 
+    def test_authorization_logout(self):
+        """test OpenID Provider flow with logout"""
+        sleep(1)
+        # Bootstrap all needed objects
+        authorization_flow = Flow.objects.get(
+            slug="default-provider-authorization-implicit-consent"
+        )
+        provider = OAuth2Provider.objects.create(
+            name="grafana",
+            client_type=ClientTypes.CONFIDENTIAL,
+            client_id=self.client_id,
+            client_secret=self.client_secret,
+            rsa_key=CertificateKeyPair.objects.first(),
+            redirect_uris="http://localhost:3000/login/generic_oauth",
+            authorization_flow=authorization_flow,
+            response_type=ResponseTypes.CODE,
+        )
+        provider.property_mappings.set(
+            ScopeMapping.objects.filter(
+                scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE]
+            )
+        )
+        provider.save()
+        Application.objects.create(
+            name="Grafana", slug=APPLICATION_SLUG, provider=provider,
+        )
+
+        self.driver.get("http://localhost:3000")
+        self.driver.find_element(By.CLASS_NAME, "btn-service--oauth").click()
+        self.driver.find_element(By.ID, "id_uid_field").click()
+        self.driver.find_element(By.ID, "id_uid_field").send_keys(USER().username)
+        self.driver.find_element(By.ID, "id_uid_field").send_keys(Keys.ENTER)
+        self.driver.find_element(By.ID, "id_password").send_keys(USER().username)
+        self.driver.find_element(By.ID, "id_password").send_keys(Keys.ENTER)
+        self.driver.find_element(By.XPATH, "//a[contains(@href, '/profile')]").click()
+        self.assertEqual(
+            self.driver.find_element(By.CLASS_NAME, "page-header__title").text,
+            USER().name,
+        )
+        self.assertEqual(
+            self.driver.find_element(By.CSS_SELECTOR, "input[name=name]").get_attribute(
+                "value"
+            ),
+            USER().name,
+        )
+        self.assertEqual(
+            self.driver.find_element(
+                By.CSS_SELECTOR, "input[name=email]"
+            ).get_attribute("value"),
+            USER().email,
+        )
+        self.assertEqual(
+            self.driver.find_element(
+                By.CSS_SELECTOR, "input[name=login]"
+            ).get_attribute("value"),
+            USER().email,
+        )
+        self.driver.find_element(By.CSS_SELECTOR, "[href='/logout']").click()
+        self.wait_for_url(
+            self.url(
+                "passbook_providers_oauth2:end-session",
+                application_slug=APPLICATION_SLUG,
+            )
+        )
+        self.driver.find_element(By.ID, "logout").click()
+
     def test_authorization_consent_explicit(self):
         """test OpenID Provider flow (default authorization flow with explicit consent)"""
         sleep(1)
@@ -195,7 +268,7 @@ class TestProviderOAuth2OIDC(SeleniumTestCase):
         )
         provider.save()
         app = Application.objects.create(
-            name="Grafana", slug="grafana", provider=provider,
+            name="Grafana", slug=APPLICATION_SLUG, provider=provider,
         )
 
         self.driver.get("http://localhost:3000")
@@ -271,7 +344,7 @@ class TestProviderOAuth2OIDC(SeleniumTestCase):
         )
         provider.save()
         app = Application.objects.create(
-            name="Grafana", slug="grafana", provider=provider,
+            name="Grafana", slug=APPLICATION_SLUG, provider=provider,
         )
 
         negative_policy = ExpressionPolicy.objects.create(
diff --git a/passbook/providers/oauth2/templates/providers/oauth2/end_session.html b/passbook/providers/oauth2/templates/providers/oauth2/end_session.html
new file mode 100644
index 000000000..c43029483
--- /dev/null
+++ b/passbook/providers/oauth2/templates/providers/oauth2/end_session.html
@@ -0,0 +1,36 @@
+{% extends 'login/base_full.html' %}
+
+{% load static %}
+{% load i18n %}
+{% load passbook_utils %}
+
+{% block title %}
+{% trans 'End session' %}
+{% endblock %}
+
+{% block card_title %}
+{% blocktrans with application=application.name %}
+You've logged out of {{ application }}.
+{% endblocktrans %}
+{% endblock %}
+
+{% block card %}
+<form method="POST" class="pf-c-form">
+    {% if message %}
+    <h3>{% trans message %}</h3>
+    {% endif %}
+
+    <a id="pb-back-home" href="{% url 'passbook_core:overview' %}" class="pf-c-button pf-m-primary">{% trans 'Go back to passbook' %}</a>
+
+    <a id="logout" href="{% url 'passbook_flows:default-invalidation' %}" class="pf-c-button pf-m-secondary">{% trans 'Log out of passbook' %}</a>
+
+    {% if application.get_launch_url %}
+    <a href="{{ application.get_launch_url }}" class="pf-c-button pf-m-secondary">
+        {% blocktrans with application=application.name %}
+            Log back into {{ application }}
+        {% endblocktrans %}
+    </a>
+    {% endif %}
+
+</form>
+{% endblock %}
diff --git a/passbook/providers/oauth2/urls.py b/passbook/providers/oauth2/urls.py
index 7ccd2b00a..725f26a35 100644
--- a/passbook/providers/oauth2/urls.py
+++ b/passbook/providers/oauth2/urls.py
@@ -20,12 +20,16 @@ urlpatterns = [
         csrf_exempt(protected_resource_view([SCOPE_OPENID])(UserInfoView.as_view())),
         name="userinfo",
     ),
-    path("end-session/", EndSessionView.as_view(), name="end-session",),
     path(
         "introspect/",
         csrf_exempt(TokenIntrospectionView.as_view()),
         name="token-introspection",
     ),
+    path(
+        "<slug:application_slug>/end-session/",
+        EndSessionView.as_view(),
+        name="end-session",
+    ),
     path("<slug:application_slug>/jwks/", JWKSView.as_view(), name="jwks"),
     path(
         "<slug:application_slug>/.well-known/openid-configuration",
diff --git a/passbook/providers/oauth2/views/provider.py b/passbook/providers/oauth2/views/provider.py
index 000f6ecd6..4b9fe9757 100644
--- a/passbook/providers/oauth2/views/provider.py
+++ b/passbook/providers/oauth2/views/provider.py
@@ -32,7 +32,10 @@ class ProviderInfoView(View):
                 reverse("passbook_providers_oauth2:userinfo")
             ),
             "end_session_endpoint": self.request.build_absolute_uri(
-                reverse("passbook_providers_oauth2:end-session")
+                reverse(
+                    "passbook_providers_oauth2:end-session",
+                    kwargs={"application_slug": provider.application.slug},
+                )
             ),
             "introspection_endpoint": self.request.build_absolute_uri(
                 reverse("passbook_providers_oauth2:token-introspection")
diff --git a/passbook/providers/oauth2/views/session.py b/passbook/providers/oauth2/views/session.py
index 5794c13a0..1a889a907 100644
--- a/passbook/providers/oauth2/views/session.py
+++ b/passbook/providers/oauth2/views/session.py
@@ -1,45 +1,22 @@
 """passbook OAuth2 Session Views"""
-from urllib.parse import parse_qs, urlencode, urlsplit, urlunsplit
+from typing import Any, Dict
 
-from django.contrib.auth.views import LogoutView
-from django.http import HttpRequest, HttpResponse
 from django.shortcuts import get_object_or_404
+from django.views.generic.base import TemplateView
 
 from passbook.core.models import Application
-from passbook.providers.oauth2.models import OAuth2Provider
-from passbook.providers.oauth2.utils import client_id_from_id_token
 
 
-class EndSessionView(LogoutView):
+class EndSessionView(TemplateView):
     """Allow the client to end the Session"""
 
-    def dispatch(
-        self, request: HttpRequest, application_slug: str, *args, **kwargs
-    ) -> HttpResponse:
+    template_name = "providers/oauth2/end_session.html"
 
-        application = get_object_or_404(Application, slug=application_slug)
-        provider: OAuth2Provider = get_object_or_404(
-            OAuth2Provider, pk=application.provider_id
+    def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
+        context = super().get_context_data(**kwargs)
+
+        context["application"] = get_object_or_404(
+            Application, slug=self.kwargs["application_slug"]
         )
 
-        id_token_hint = request.GET.get("id_token_hint", "")
-        post_logout_redirect_uri = request.GET.get("post_logout_redirect_uri", "")
-        state = request.GET.get("state", "")
-
-        if id_token_hint:
-            client_id = client_id_from_id_token(id_token_hint)
-            try:
-                provider = OAuth2Provider.objects.get(client_id=client_id)
-                if post_logout_redirect_uri in provider.post_logout_redirect_uris:
-                    if state:
-                        uri = urlsplit(post_logout_redirect_uri)
-                        query_params = parse_qs(uri.query)
-                        query_params["state"] = state
-                        uri = uri._replace(query=urlencode(query_params, doseq=True))
-                        self.next_page = urlunsplit(uri)
-                    else:
-                        self.next_page = post_logout_redirect_uri
-            except OAuth2Provider.DoesNotExist:
-                pass
-
-        return super().dispatch(request, *args, **kwargs)
+        return context