diff --git a/README.md b/README.md
index 5b80448b..2fda5570 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,8 @@ This repository contains samples demonstrating **how to use [OpenIddict](https:/
- **[Angular and Blazor samples](https://github.com/damienbod/AspNetCoreOpeniddict)** by [Damien Bowden](https://github.com/damienbod)
- **[Experimental MAUI (WinUI-only) sample](https://github.com/kevinchalet/openiddict-core/tree/maui_winui_sample/sandbox/OpenIddict.Sandbox.Maui.Client)** by [Kévin Chalet](https://github.com/kevinchalet)
+
+ - **[OIDC Session Management sample](https://github.com/GREsau/openiddict-session-management-sample)** by [Graham Esau](https://github.com/GREsau)
## Certification
diff --git a/samples/Contruum/Contruum.Server/Pages/Connect/EndSession.cshtml b/samples/Contruum/Contruum.Server/Pages/Connect/EndSession.cshtml
new file mode 100644
index 00000000..817884ca
--- /dev/null
+++ b/samples/Contruum/Contruum.Server/Pages/Connect/EndSession.cshtml
@@ -0,0 +1,19 @@
+@page
+@model Contruum.Server.Pages.Connect.EndSessionModel
+@using Microsoft.Extensions.Primitives
+
+
+
Log out
+
Are you sure you want to sign out?
+
+
+
diff --git a/samples/Contruum/Contruum.Server/Pages/Connect/EndSession.cshtml.cs b/samples/Contruum/Contruum.Server/Pages/Connect/EndSession.cshtml.cs
new file mode 100644
index 00000000..f95b0da1
--- /dev/null
+++ b/samples/Contruum/Contruum.Server/Pages/Connect/EndSession.cshtml.cs
@@ -0,0 +1,30 @@
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using OpenIddict.Server.AspNetCore;
+
+namespace Contruum.Server.Pages.Connect;
+
+public class EndSessionModel : PageModel
+{
+ public IActionResult OnGet()
+ {
+ return Page();
+ }
+
+ public async Task OnPostAsync()
+ {
+ await HttpContext.SignOutAsync();
+
+ // Returning a SignOutResult will ask OpenIddict to redirect the user agent
+ // to the post_logout_redirect_uri specified by the client application or to
+ // the RedirectUri specified in the authentication properties if none was set.
+ return SignOut(
+ authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
+ properties: new AuthenticationProperties
+ {
+ RedirectUri = "/"
+ });
+ }
+}
diff --git a/samples/Contruum/Contruum.Server/Startup.cs b/samples/Contruum/Contruum.Server/Startup.cs
index c326e4f1..5a23830c 100644
--- a/samples/Contruum/Contruum.Server/Startup.cs
+++ b/samples/Contruum/Contruum.Server/Startup.cs
@@ -69,11 +69,13 @@ public void ConfigureServices(IServiceCollection services)
options.SetAuthorizationEndpointUris(Configuration["OpenIddict:Endpoints:Authorization"]!)
.SetTokenEndpointUris(Configuration["OpenIddict:Endpoints:Token"]!)
.SetIntrospectionEndpointUris(Configuration["OpenIddict:Endpoints:Introspection"]!)
- .SetUserinfoEndpointUris(Configuration["OpenIddict:Endpoints:Userinfo"]!);
+ .SetUserinfoEndpointUris(Configuration["OpenIddict:Endpoints:Userinfo"]!)
+ .SetLogoutEndpointUris(Configuration["OpenIddict:Endpoints:Logout"]!);
- // Enable the authorization code, implicit and the refresh token flows.
+ // Enable the authorization code, implicit, hybrid and the refresh token flows.
options.AllowAuthorizationCodeFlow()
.AllowImplicitFlow()
+ .AllowHybridFlow()
.AllowRefreshTokenFlow();
// Expose all the supported claims in the discovery document.
@@ -93,7 +95,8 @@ public void ConfigureServices(IServiceCollection services)
// so that token requests are automatically handled by OpenIddict.
options.UseAspNetCore()
.EnableAuthorizationEndpointPassthrough()
- .EnableAuthorizationRequestCaching();
+ .EnableAuthorizationRequestCaching()
+ .EnableLogoutEndpointPassthrough();
// Register the event handler responsible for populating userinfo responses.
options.AddEventHandler(options =>
diff --git a/samples/Contruum/Contruum.Server/appsettings.json b/samples/Contruum/Contruum.Server/appsettings.json
index a1c47230..4c3a6e4d 100644
--- a/samples/Contruum/Contruum.Server/appsettings.json
+++ b/samples/Contruum/Contruum.Server/appsettings.json
@@ -39,10 +39,12 @@
"ClientId": "oidc_certification_app_1",
"ClientSecret": "secret_secret_secret",
"RedirectUris": [ "https://www.certification.openid.net/test/a/d6e0d2a6-003e-4721-8b67-a24380468aa8/callback" ],
+ "PostLogoutRedirectUris": [ "https://www.certification.openid.net/test/a/d6e0d2a6-003e-4721-8b67-a24380468aa8/post_logout_redirect" ],
"Type": "confidential",
"Permissions": [
"ept:authorization",
"ept:token",
+ "ept:logout",
"gt:authorization_code",
"gt:implicit",
"gt:refresh_token",
@@ -64,10 +66,12 @@
"ClientId": "oidc_certification_app_2",
"ClientSecret": "secret_secret_secret",
"RedirectUris": [ "https://www.certification.openid.net/test/a/d6e0d2a6-003e-4721-8b67-a24380468aa8/callback" ],
+ "PostLogoutRedirectUris": [ "https://www.certification.openid.net/test/a/d6e0d2a6-003e-4721-8b67-a24380468aa8/post_logout_redirect" ],
"Type": "confidential",
"Permissions": [
"ept:authorization",
"ept:token",
+ "ept:logout",
"gt:authorization_code",
"gt:implicit",
"gt:refresh_token",
@@ -90,7 +94,8 @@
"Authorization": "connect/authorize",
"Introspection": "connect/introspect",
"Token": "connect/token",
- "Userinfo": "connect/userinfo"
+ "Userinfo": "connect/userinfo",
+ "Logout": "connect/endsession"
},
"Scopes": [