diff --git a/guides/getting-started/creating-your-own-server-instance.md b/guides/getting-started/creating-your-own-server-instance.md
index a30abf6..dec4ca2 100644
--- a/guides/getting-started/creating-your-own-server-instance.md
+++ b/guides/getting-started/creating-your-own-server-instance.md
@@ -16,8 +16,8 @@ If you don't want to start from one of the recommended samples, you'll need to:
- **Update your `.csproj` file** to reference the latest `OpenIddict.AspNetCore` and `OpenIddict.EntityFrameworkCore` packages:
```xml
-
-
+
+
```
- **Register your Entity Framework Core database context and configure the OpenIddict core services** in `Program.cs`
diff --git a/guides/getting-started/implementing-token-validation-in-your-apis.md b/guides/getting-started/implementing-token-validation-in-your-apis.md
index 4997923..0d9152b 100644
--- a/guides/getting-started/implementing-token-validation-in-your-apis.md
+++ b/guides/getting-started/implementing-token-validation-in-your-apis.md
@@ -12,7 +12,7 @@ If you don't want to start from one of the recommended samples, you'll need to:
- **Reference the `OpenIddict.AspNetCore` package**:
```xml
-
+
```
- **Configure the OpenIddict validation services** in `Startup.ConfigureServices`:
diff --git a/guides/getting-started/integrating-with-a-remote-server-instance.md b/guides/getting-started/integrating-with-a-remote-server-instance.md
index 12e0704..2522775 100644
--- a/guides/getting-started/integrating-with-a-remote-server-instance.md
+++ b/guides/getting-started/integrating-with-a-remote-server-instance.md
@@ -18,7 +18,7 @@ in web and desktop applications. If you want to use a non-interactive flow like
- **Update your `.csproj` file** to reference the latest `OpenIddict` package:
```xml
-
+
```
- **Configure the OpenIddict client services** in `Program.cs` (or `Startup.cs` if you use the regular ASP.NET Core web host):
@@ -72,8 +72,8 @@ If you don't want to start from one of the recommended samples, you'll need to:
- **Update your `.csproj` file** to reference the latest `OpenIddict.AspNetCore` and `OpenIddict.EntityFrameworkCore` packages:
```xml
-
-
+
+
```
- **Configure the OpenIddict core services** in `Program.cs` (or `Startup.cs`, depending on whether you're using the minimal host or the regular host):
diff --git a/guides/migration/60-to-70.md b/guides/migration/60-to-70.md
index 5acb08e..b8bfec1 100644
--- a/guides/migration/60-to-70.md
+++ b/guides/migration/60-to-70.md
@@ -14,10 +14,10 @@ For that, update your `.csproj` file to reference the `OpenIddict` 7.x packages.
```xml
-
+
-
+
```
diff --git a/integrations/aspnet-core.md b/integrations/aspnet-core.md
index ab7e873..7bdd5d4 100644
--- a/integrations/aspnet-core.md
+++ b/integrations/aspnet-core.md
@@ -29,9 +29,9 @@ To configure the ASP.NET Core integration, you'll need to:
(depending on whether you need the client and/or server and/or validation features in your project):
```xml
-
-
-
+
+
+
```
- **Call `UseAspNetCore()` for each OpenIddict feature (client, server and validation) you want to add**:
diff --git a/integrations/entity-framework-core.md b/integrations/entity-framework-core.md
index 89276eb..644b5d8 100644
--- a/integrations/entity-framework-core.md
+++ b/integrations/entity-framework-core.md
@@ -6,7 +6,7 @@ To configure OpenIddict to use Entity Framework Core as the database for applica
- **Reference the `OpenIddict.EntityFrameworkCore` package**:
```xml
-
+
```
- **Create a database context deriving from `DbContext` (or `IdentityDbContext` when using ASP.NET Core Identity)**:
diff --git a/integrations/entity-framework.md b/integrations/entity-framework.md
index 07191d5..b1fae61 100644
--- a/integrations/entity-framework.md
+++ b/integrations/entity-framework.md
@@ -6,7 +6,7 @@ To configure OpenIddict to use Entity Framework 6.x as the database for applicat
- **Reference the `OpenIddict.EntityFramework` package**:
```xml
-
+
```
- **Create a database context deriving from `DbContext` and register the OpenIddict entities in the model**:
diff --git a/integrations/mongodb.md b/integrations/mongodb.md
index 1b222c4..4b46b88 100644
--- a/integrations/mongodb.md
+++ b/integrations/mongodb.md
@@ -6,7 +6,7 @@ To configure OpenIddict to use MongoDB as the database for applications, authori
- **Reference the `OpenIddict.MongoDb` package**:
```xml
-
+
```
- **Configure OpenIddict to use the MongoDB stores**:
diff --git a/integrations/operating-systems.md b/integrations/operating-systems.md
index 955284e..632723c 100644
--- a/integrations/operating-systems.md
+++ b/integrations/operating-systems.md
@@ -295,7 +295,7 @@ To configure the operating system integration, you'll need to:
- **Reference the `OpenIddict.Client.SystemIntegration` package**:
```xml
-
+
```
- **Call `UseSystemIntegration()` in the client options**:
diff --git a/integrations/owin.md b/integrations/owin.md
new file mode 100644
index 0000000..8b6f4b2
--- /dev/null
+++ b/integrations/owin.md
@@ -0,0 +1,378 @@
+# OWIN integration
+
+Thanks to their native OWIN integrations, the client, server and validation features offered by OpenIddict can be used in any
+ASP.NET 4.6.2+ application, independently of whether they are using Web Forms, MVC controllers, Web API controllers or raw OWIN middleware.
+
+## Supported versions
+
+| `Microsoft.Owin` version | .NET runtime version | Support status |
+|--------------------------|----------------------|---------------------------------------|
+| `Microsoft.Owin` 4.2 | .NET Framework 4.6.2 | :heavy_check_mark: (with limitations) |
+| `Microsoft.Owin` 4.2 | .NET Framework 4.7.2 | :heavy_check_mark: |
+| `Microsoft.Owin` 4.2 | .NET Framework 4.8 | :heavy_check_mark: |
+
+> [!NOTE]
+> **The following features are not available when targeting .NET Framework 4.6.2**:
+> - X.509 development encryption/signing certificates: calling `AddDevelopmentEncryptionCertificate()` or `AddDevelopmentSigningCertificate()`
+> will result in a `PlatformNotSupportedException` being thrown at runtime if no valid development certificate can be found and a new one must be generated.
+> - X.509 ECDSA signing certificates/keys: calling `AddSigningCertificate()` or `AddSigningKey()`
+> with an ECDSA certificate/key will always result in a `PlatformNotSupportedException` being thrown at runtime.
+
+## Basic configuration
+
+To configure the OWIN integration, you'll need to:
+ - **Reference the `OpenIddict.Client.Owin` and/or `OpenIddict.Server.Owin` and/or
+ `OpenIddict.Validation.Owin` packages**
+ (depending on whether you need the client and/or server and/or validation features in your project):
+
+ ```xml
+
+
+
+ ```
+
+ - **Call `UseOwin()` for each OpenIddict feature (client, server and validation) you want to add**:
+
+ ```csharp
+ services.AddOpenIddict()
+ .AddCore(options =>
+ {
+ // ...
+ })
+ .AddClient(options =>
+ {
+ // ...
+
+ options.UseOwin();
+ })
+ .AddServer(options =>
+ {
+ // ...
+
+ options.UseOwin();
+ })
+ .AddValidation(options =>
+ {
+ // ...
+
+ options.UseOwin();
+ });
+ ```
+
+> [!WARNING]
+> OpenIddict integrates with OWIN using an `AuthenticationMiddleware`.
+>
+> As such, it is critical that the ASP.NET Core authentication middleware be registered at the
+> right place in the pipeline (i.e after `app.UseCors()` and before `app.UseEndpoint()`):
+>
+> ```csharp
+> app.UseDeveloperExceptionPage();
+> app.UseStatusCodePagesWithReExecute("/error");
+>
+> app.UseRouting();
+> app.UseCors();
+>
+> app.UseAuthentication(); // [!code warning]
+> app.UseAuthorization(); // [!code warning]
+>
+> app.UseEndpoints(options =>
+> {
+> options.MapControllers();
+> options.MapDefaultControllerRoute();
+> });
+> ```
+
+## Advanced configuration
+
+### Transport security requirement
+
+By default, the OpenIddict server ASP.NET Core integration will refuse to serve non-HTTPS
+requests for security reasons and will return an error page to the caller.
+
+For the same reason, the OpenIddict client ASP.NET Core host will, by default, refuse to start authentication challenges
+from a non-HTTPS page and will automatically throw an exception to abort these unsafe operations.
+
+While disabling this requirement is strongly discouraged in most cases, it can be disabled using the `DisableTransportSecurityRequirement()` API:
+
+```csharp
+services.AddOpenIddict()
+ .AddClient(options =>
+ {
+ options.UseOwin()
+ .DisableTransportSecurityRequirement();
+ })
+ .AddServer(options =>
+ {
+ options.UseOwin()
+ .DisableTransportSecurityRequirement();
+ });
+```
+
+> [!CAUTION]
+> **The transport security requirement SHOULD NEVER be disabled in production**, even when using a reverse proxy doing TLS termination: if requests
+> are rejected by OpenIddict when doing TLS termination, this very likely means that the ASP.NET Core application was not properly configured to
+> extract and restore the original request details (and more specifically, `HttpRequest.Scheme`).
+>
+> For more information,
+> read [Configure ASP.NET Core to work with proxy servers and load balancers](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer).
+
+### Pass-through mode
+
+The ASP.NET Core integration offered by the OpenIddict client and server stacks offers built-in pass-through support
+for some of the built-in endpoints (typically, endpoints for which users will want to provide custom logic).
+
+> [!NOTE]
+> For more information on the pass-through mode, read [Pass-through support](/introduction.md#pass-through-support).
+
+Pass-through mode for a specific endpoint can be enabled using the APIs exposed by `OpenIddictClientOwinBuilder`
+or `OpenIddictServerOwinBuilder`. E.g for the authorization endpoint:
+
+```csharp
+services.AddOpenIddict()
+ .AddServer(options =>
+ {
+ // ...
+
+ options.UseOwin()
+ .EnableAuthorizationEndpointPassthrough();
+ });
+```
+
+Once enabled, you can handle authorization requests in an MVC controller or a minimal API handler:
+
+```csharp
+app.MapMethods("authorize", [HttpMethods.Get, HttpMethods.Post], async (HttpContext context) =>
+{
+ // Resolve the claims stored in the cookie created after the GitHub authentication dance.
+ // If the principal cannot be found, trigger a new challenge to redirect the user to GitHub.
+ //
+ // For scenarios where the default authentication handler configured in the ASP.NET Core
+ // authentication options shouldn't be used, a specific scheme can be specified here.
+ var principal = (await context.AuthenticateAsync())?.Principal;
+ if (principal is null)
+ {
+ var properties = new AuthenticationProperties
+ {
+ RedirectUri = context.Request.GetEncodedUrl()
+ };
+
+ return Results.Challenge(properties, [Providers.GitHub]);
+ }
+
+ var identifier = principal.FindFirst(ClaimTypes.NameIdentifier)!.Value;
+
+ // Create the claims-based identity that will be used by OpenIddict to generate tokens.
+ var identity = new ClaimsIdentity(
+ authenticationType: TokenValidationParameters.DefaultAuthenticationType,
+ nameType: Claims.Name,
+ roleType: Claims.Role);
+
+ // Import a few select claims from the identity stored in the local cookie.
+ identity.AddClaim(new Claim(Claims.Subject, identifier));
+ identity.AddClaim(new Claim(Claims.Name, identifier).SetDestinations(Destinations.AccessToken));
+ identity.AddClaim(new Claim(Claims.PreferredUsername, identifier).SetDestinations(Destinations.AccessToken));
+
+ return Results.SignIn(new ClaimsPrincipal(identity), properties: null, OpenIddictServerOwinDefaults.AuthenticationScheme);
+});
+```
+
+### Status code pages middleware integration
+
+Both the OpenIddict client and server ASP.NET Core hosts offer an option to render error pages using
+[ASP.NET Core's status code pages middleware](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling#usestatuscodepages).
+
+To enable this feature, you can use the dedicated `EnableStatusCodePagesIntegration()` API:
+
+```csharp
+services.AddOpenIddict()
+ .AddClient(options =>
+ {
+ options.UseOwin()
+ .EnableStatusCodePagesIntegration();
+ });
+```
+
+```csharp
+services.AddOpenIddict()
+ .AddServer(options =>
+ {
+ options.UseOwin()
+ .EnableStatusCodePagesIntegration();
+ });
+```
+
+> [!WARNING]
+> You'll need to make sure the status code pages middleware is registered at an appropriate place
+> in the ASP.NET Core pipeline (i.e before `app.UseAuthentication()`):
+>
+> ```csharp
+> app.UseDeveloperExceptionPage();
+> app.UseStatusCodePagesWithReExecute("/error");
+>
+> app.UseRouting();
+> app.UseCors();
+>
+> app.UseAuthentication();
+> app.UseAuthorization();
+>
+> app.UseEndpoints(options =>
+> {
+> options.MapControllers();
+> options.MapDefaultControllerRoute();
+> });
+> ```
+
+Once enabled, create an error controller that will be invoked to handle errored responses:
+
+```csharp
+public class ErrorController : Controller
+{
+ [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true), Route("~/error")]
+ public IActionResult Error()
+ {
+ // If the error originated from the OpenIddict client, render the error details.
+ var response = HttpContext.GetOpenIddictClientResponse();
+ if (response is not null)
+ {
+ return View(new ErrorViewModel
+ {
+ Error = response.Error,
+ ErrorDescription = response.ErrorDescription
+ });
+ }
+
+ return View(new ErrorViewModel());
+ }
+}
+```
+
+```csharp
+public class ErrorController : Controller
+{
+ [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true), Route("~/error")]
+ public IActionResult Error()
+ {
+ // If the error originated from the OpenIddict server, render the error details.
+ var response = HttpContext.GetOpenIddictServerResponse();
+ if (response is not null)
+ {
+ return View(new ErrorViewModel
+ {
+ Error = response.Error,
+ ErrorDescription = response.ErrorDescription
+ });
+ }
+
+ return View(new ErrorViewModel());
+ }
+}
+```
+
+> [!TIP]
+> If you're using both the OpenIddict client and the OpenIddict server in the same application, you can configure both
+> stacks to use the status code pages middleware. In this case, you'll need to resolve the error response using both
+> `HttpContext.GetOpenIddictClientResponse()` and `HttpContext.GetOpenIddictServerResponse()`:
+>
+> ```csharp
+> public class ErrorController : Controller
+> {
+> [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true), Route("~/error")]
+> public IActionResult Error()
+> {
+> // If the error originated from the OpenIddict client or server, render the error details.
+> var response = HttpContext.GetOpenIddictClientResponse() ?? HttpContext.GetOpenIddictServerResponse();
+> if (response is not null)
+> {
+> return View(new ErrorViewModel
+> {
+> Error = response.Error,
+> ErrorDescription = response.ErrorDescription
+> });
+> }
+>
+> return View(new ErrorViewModel());
+> }
+> }
+> ```
+
+### Authorization and end session request caching
+
+To simplify flowing large authorization or logout requests, the OpenIddict server ASP.NET Core integration includes a built-in feature
+that allows generating a unique `request_uri` and caching the received requests in a request token persisted in OpenIddict's tokens table: when this feature is enabled,
+an automatic redirection to the current page with the other parameters removed is triggered by OpenIddict and the token entry is redeemed
+once the authorization or logout demand has been completed by the user.
+
+To enable this feature, you need to use the dedicated `EnableAuthorizationRequestCaching()` and/or `EnableEndSessionEndpointPassthrough()` APIs:
+
+```csharp
+services.AddOpenIddict()
+ .AddServer(options =>
+ {
+ options.EnableAuthorizationRequestCaching()
+ .EnableEndSessionEndpointPassthrough();
+ });
+```
+
+### Authentication scheme forwarding
+
+To simplify triggering authentication operations for a specific client registration, the OpenIddict client offers a built-in authentication scheme
+forwarding feature that allows using the provider name assigned to a client registration as an authentication scheme in ASP.NET Core:
+
+```csharp
+app.MapGet("challenge", () => Results.Challenge(properties: null, authenticationSchemes: [Providers.GitHub]));
+```
+
+This feature is enabled by default but can be disabled if necessary using `DisableAutomaticAuthenticationSchemeForwarding()`:
+
+```csharp
+services.AddOpenIddict()
+ .AddClient(options =>
+ {
+ options.UseOwin()
+ .DisableAutomaticAuthenticationSchemeForwarding();
+ });
+```
+
+If you need to enable forwarding for specific registrations only, you can use the advanced
+`AddForwardedAuthenticationScheme()` API to selectively add the schemes you want:
+
+```csharp
+services.AddOpenIddict()
+ .AddClient(options =>
+ {
+ options.UseOwin()
+ .DisableAutomaticAuthenticationSchemeForwarding()
+ .AddForwardedAuthenticationScheme(provider: "Contoso", caption: "Contoso Intranet login");
+ });
+```
+
+When automatic forwarding is disabled, authentication operations cannot directly use the provider name as an authentication scheme
+if no explicit forwarding was configured and must instead use `OpenIddictClientOwinDefaults.AuthenticationScheme` with an
+`AuthenticationProperties` instance containing the provider name, the issuer URI or the registration identifier:
+
+```csharp
+app.MapGet("challenge", () =>
+{
+ var properties = new AuthenticationProperties(new Dictionary
+ {
+ [OpenIddictClientOwinConstants.Properties.ProviderName] = Providers.GitHub
+ });
+
+ return Results.Challenge(properties, authenticationSchemes: [OpenIddictClientOwinDefaults.AuthenticationScheme]);
+});
+```
+
+### JSON responses indentation
+
+By default, the OpenIddict server ASP.NET Core host will return indented JSON responses to make them easier to read.
+
+Users who prefer disabling indentation for JSON responses can do so by calling `SuppressJsonResponseIndentation()`:
+
+```csharp
+services.AddOpenIddict()
+ .AddServer(options =>
+ {
+ options.UseOwin()
+ .SuppressJsonResponseIndentation();
+ });
+```
diff --git a/integrations/quartz.md b/integrations/quartz.md
index f1fdc11..c3f6941 100644
--- a/integrations/quartz.md
+++ b/integrations/quartz.md
@@ -6,7 +6,7 @@ To configure OpenIddict to use Quartz.NET to perform automated cleanup tasks, yo
- **Reference the `OpenIddict.Quartz` package**:
```xml
-
+
```
- **Register the Quartz.NET services and configure it to use dependency injection and an in-memory store**:
diff --git a/integrations/system-net-http.md b/integrations/system-net-http.md
index 4ffe01d..f01b856 100644
--- a/integrations/system-net-http.md
+++ b/integrations/system-net-http.md
@@ -15,8 +15,8 @@ To configure the `System.Net.Http` integration, you'll need to:
(depending on whether you need the client and/or validation features in your project):
```xml
-
-
+
+
```
- **Call `UseSystemNetHttp()` for each OpenIddict feature (client and validation) you want to add**:
diff --git a/integrations/web-providers.md b/integrations/web-providers.md
index 611a81d..f4c12c6 100644
--- a/integrations/web-providers.md
+++ b/integrations/web-providers.md
@@ -169,7 +169,7 @@ To configure the `System.Net.Http` integration, you'll need to:
- **Reference the `OpenIddict.Client.WebIntegration` package**:
```xml
-
+
```
- **Call `UseWebProviders()` in the client options**: