From 2efcee66b2b092b872a91cd46242a4821c075ae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= Date: Wed, 22 Apr 2026 05:46:53 +0200 Subject: [PATCH] Bump OpenIddict to 7.5.0 --- .../creating-your-own-server-instance.md | 4 +- ...lementing-token-validation-in-your-apis.md | 2 +- ...tegrating-with-a-remote-server-instance.md | 6 +- guides/migration/60-to-70.md | 4 +- integrations/aspnet-core.md | 6 +- integrations/entity-framework-core.md | 2 +- integrations/entity-framework.md | 2 +- integrations/mongodb.md | 2 +- integrations/operating-systems.md | 2 +- integrations/owin.md | 378 ++++++++++++++++++ integrations/quartz.md | 2 +- integrations/system-net-http.md | 4 +- integrations/web-providers.md | 2 +- 13 files changed, 397 insertions(+), 19 deletions(-) create mode 100644 integrations/owin.md 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**: