OpenIddict 6.0 general availability

Ding ding ding... OpenIddict 6.0 is coming to town! 🎉

What's new?

Many of the new features already shipped in 5.x but some of them required introducing breaking changes and had to wait for 6.0:

  • The .NET 7.0 and .NET Framework 4.6.1 TFMs have been removed as these versions are no longer supported by Microsoft.

    While most OpenIddict 6.0 packages can still be used on these versions thanks to their .NET Standard 2.0 or 2.1 TFMs, doing that is strongly discouraged and users are instead encouraged to migrate to .NET 8.0 and .NET Framework 4.6.2 (or higher).

  • The OpenIddict.MongoDb and OpenIddict.MongoDb.Models packages now reference MongoDB.Driver and MongoDB.Bson 3.0.0 and are now strong-named.

The third iteration of the C# MongoDB driver no longer supports .NET Standard 2.0 and requires .NET Framework 4.7.2 as the minimum version: OpenIddict users relying on the MongoDB integration and using the OpenIddict.MongoDb or OpenIddict.MongoDb.Models packages in projects targeting .NET Standard 2.0 or .NET Framework < 4.7.2 will need to update their projects when migrating to OpenIddict 6.0.

  • Some of the server endpoints have been renamed in OpenIddict 6.0 to be more specific or more closely match the official names. While it's a massive change, it should help reduce ambiguities and make migrating from other OAuth 2.0/OIDC stacks to OpenIddict easier:

    • Cryptography endpoint -> JSON Web Key Set endpoint.
    • Device endpoint -> Device authorization endpoint.
    • Logout endpoint -> End-session endpoint.
    • Userinfo endpoint -> UserInfo endpoint.
    • Verification endpoint -> End-user verification endpoint.
  • A whole new client authentication method negotiation logic was introduced in the OpenIddict client. As part of this change, complete support for mTLS in the client stack was also added to allow integrating with identity providers that require using tls_client_auth or self_signed_tls_client_auth. See https://github.com/openiddict/openiddict-core/releases/tag/6.0.0-preview1 for more information.

  • A new "claims issuer" option has been added to the client and validation stacks to allow controlling the value OpenIddict uses to populate the Claim.Issuer and Claim.OriginalIssuer properties. This option is specially useful when using the OpenIddict client in legacy ASP.NET 4.6.2+ applications using ASP.NET Identity, since the Claim.Issuer property is directly reflected in the user interface:

1
2
3
4
5
6
7
options.AddRegistration(new OpenIddictClientRegistration
{
// ...

Issuer = new Uri("https://localhost:44395/", UriKind.Absolute),
ClaimsIssuer = "Local authorization server"
});
1
2
3
4
5
6
7
options.UseWebProviders()
.AddActiveDirectoryFederationServices(options =>
{
// ...

options.SetClaimsIssuer("Contoso");
});
  • New RevokeAsync()/RevokeByApplicationIdAsync()/RevokeBySubjectAsync() APIs modeled after the existing FindAsync() and RevokeByAuthorizationIdAsync() API have been added to the authorization/token managers/stores to allow revoking authorizations and tokens based on a given application identifier or user identifier more efficiently.

  • The existing IOpenIddictAuthorizationManager.FindAsync(...) and IOpenIddictTokenManager.FindAsync(...) overloads have been merged and replaced by a single method where all the parameters are now optional (for instance, if a null subject value is specified when calling IOpenIddictAuthorizationManager.FindAsync(...), the returned collection will contain authorizations for all users).

  • The OpenIddict server now fully supports the Initiating User Registration via OpenID Connect specification: it will now validate the prompt parameter to ensure the value is supported and return the supported values in the server configuration document using the new standard prompt_values_supported node. See https://github.com/openiddict/openiddict-core/pull/2197 for more information.

As part of this change, the OpenIddictConstants.Prompts class have been renamed to OpenIddictConstants.PromptValues and the OpenIddictRequest.GetPrompts()/OpenIddictRequest.HasPrompt() extensions have been renamed to OpenIddictRequest.GetPromptValues() and OpenIddictRequest.HasPromptValue() to match the names used in this specification. If you're using these APIs, make sure you're updating the corresponding calls when migrating to OpenIddict 6.0.

  • The ASP.NET Core and OWIN integrations now include the authentication properties attached to ProcessAuthenticationContext.Properties in errored authentication results, which can be used with the client stack to retrieve custom and non-custom properties attached to the state token when using the "error pass-through mode".

  • The OpenIddict server now automatically normalizes unique "amr" claims in identity tokens to ensure a JSON array is always returned (as required by the OpenID Connect specification), even if the developer didn't explicitly use JsonClaimValueTypes.JsonArray as the claim value type.

  • New methods allowing to register multiple certificates and keys at once have been added to the client/server/validation builders (thanks ionite34! ❤️)

  • Zendesk and EVE Online are now supported by the OpenIddict web providers package (thanks mozts2005 and kalaveijo! ❤️)

Migration

While OpenIddict 6.0 comes with some breaking changes, the migration process should be fairly easy. To help users with this process, an OpenIddict 6.0 migration guide was added to the documentation.

OpenIddict 6.0 is fully compatible with ASP.NET Core 2.1 (on .NET Framework), ASP.NET Core 6.0, ASP.NET Core 8.0 and ASP.NET Core 9.0, so the migration can be done without having to upgrade to the latest .NET runtime/ASP.NET Core version: when possible, it is even recommended to decouple the .NET runtime/OpenIddict updates for a smoother upgrade.

Read more

OpenIddict 5.0 general availability

Almost exactly a year after OpenIddict's last major release, I'm very pleased to announce that 5.0 is now generally available! 🎉

What's new?

While most of the new features were already gradually added to the 4.x branch throughout 2023, some of them required introducing breaking changes and had to wait for 5.0:

  • Relaxed redirect_uri comparison policies for native applications.
  • Per-client static token lifetimes.
  • Client assertions support for the server and validation stacks.

If you're interested in learning more about these new features, don't miss this post: Introducing native applications, per-client token lifetimes and client assertions support in OpenIddict 5.0 preview1.

Migration

While OpenIddict 5.0 comes with some breaking changes, the migration process should be fairly easy. To help users with this process, an OpenIddict 5.0 migration guide was added to the documentation.

OpenIddict 5.0 is fully compatible with ASP.NET Core 2.1 (on .NET Framework), ASP.NET Core 6.0, ASP.NET Core 7.0 and ASP.NET Core 8.0, so the migration can be done without having to upgrade to the latest .NET runtime/ASP.NET Core version.

Read more

Introducing native applications, per-client token lifetimes and client assertions support in OpenIddict 5.0 preview1

Earlier today, the first OpenIddict 5.0 preview was pushed to NuGet.org 🎉

As always, all the changes can be found on GitHub but here's a recap of the most interesting ones:

What's new?

This major release introduces breaking changes that require applying migrations to update the database schema. As such it is not recommended to use it in production or in tandem with an existing deployment using OpenIddict 4.x.

Relaxed redirect_uri comparisons for native applications

While the OAuth 2.0 and OpenID Connect specifications explicitly mandated the use of the "simple string comparison" logic – put simply, a byte-by-byte comparison – newer specifications like RFC8252 (aka OAuth 2.0 for Native Apps) relaxed this policy for mobile and desktop applications to allow using dynamic ports chosen at runtime.

While OpenIddict already allowed customizing the comparison policy by overriding OpenIddictApplicationManager.ValidateRedirectUriAsync(), built-in support for native applications was not a thing.

OpenIddict 5.0 changes that by introducing a new ApplicationType property for the application entity. This property is always set to web by default, but can be explicitly set to native to opt in the relaxed comparison policy that ignores ports for local redirect_uris:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
// Note: the application must be registered as a native application to force OpenIddict
// to apply a relaxed redirect_uri validation policy that allows specifying a random port.
ApplicationType = ApplicationTypes.Native,
ClientId = "console",
ClientType = ClientTypes.Public,
ConsentType = ConsentTypes.Systematic,
DisplayName = "Console client application",
RedirectUris =
{
// Note: the port must not be explicitly specified as it is selected
// dynamically at runtime by the OpenIddict client system integration.
new Uri("http://localhost/callback/login/local")
},
Permissions =
{
Permissions.Endpoints.Authorization,
Permissions.Endpoints.Device,
Permissions.Endpoints.Token,
Permissions.GrantTypes.AuthorizationCode,
Permissions.GrantTypes.DeviceCode,
Permissions.GrantTypes.RefreshToken,
Permissions.ResponseTypes.Code,
Permissions.Scopes.Email,
Permissions.Scopes.Profile,
Permissions.Scopes.Roles,
Permissions.Prefixes.Scope + "demo_api"
},
Requirements =
{
Requirements.Features.ProofKeyForCodeExchange
}
});

To avoid ambiguities, the existing OpenIddictApplicationDescriptor.Type property (and the properties of the same name in OpenIddictEntityFrameworkApplication, OpenIddictEntityFrameworkCoreApplication and OpenIddictMongoDbApplication) have been replaced by ClientType.

Users migrating to 5.0 will be invited to update their database schema to include the new ApplicationType property and the renamed ClientType member.

Read more

Can you use the ASP.NET Core Identity API endpoints with OpenIddict?

TL;DR: yes, but please, don't do it! 🤣

If you're an avid reader of Andrew Lock's blog (certainly one of the best .NET blogs out there!), you probably figured out that the title of this blog post is very similar to his latest post, Can you use the .NET 8 Identity API endpoints with IdentityServer?, in which he describes how you could (but really shouldn't 😂) use ASP.NET Core 8's Identity API endpoints with an OAuth 2.0/OpenID Connect server stack like IdentityServer or OpenIddict.

The similarity is of course completely deliberate, as his post motivated me to write this one.

The approach described in Andrew's post – that mainly consists in using the Identity API endpoints introduced by .NET 8 to handle the user authentication part – also works with OpenIddict, so there's no point covering the same aspects twice: if you haven't read it, please read Andrew's post before reading mine.

Instead, we're going to do something even crazier ('cause why not? 😎): using OpenIddict to process token requests handled by the Identity API login endpoint... and generate token responses containing either JWT or ASP.NET Core Data Protection access tokens!

ASP.NET Core Identity's API endpoints are faux-OAuth 2.0 endpoints...

As a preamble, it's important to note that while the ASP.NET team mentioned multiple times that the Identity API endpoints are not an OAuth 2.0 implementation, it's actually a non-standard equivalent of the OAuth 2.0 resource owner password credentials grant, as I demonstrated here.

(if you're not convinced yet these endpoints are "heavily inspired" by OAuth 2.0, this message posted by Stephen Halter – who wrote the ASP.NET Core Identity API endpoints feature – should speak for itself 😁)

... that can be used with OpenIddict nevertheless

Why is this "OAuth 2.0/not OAuth 2.0" distinction important you may ask? Well, since the ASP.NET Core Identity API endpoints implement a clone of the OAuth 2.0 resource owner password credentials grant with only a few differences, it's going to be very easy to use OpenIddict's advanced events model to make it compatible with the non-standard protocol created by the ASP.NET team.

Create a minimal ASP.NET Core API and enable the ASP.NET Core Identity API endpoints

For that, create a new .csproj referencing the ASP.NET Core Identity UI, the OpenIddict ASP.NET Core metapackage and the EF Core packages:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="8.0.0-rc.1.23421.29" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.0-rc.1.23421.29" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="8.0.0-rc.1.23421.29" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0-rc.1.23419.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0-rc.1.23419.6" />
<PackageReference Include="OpenIddict.AspNetCore" Version="4.8.0" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="4.8.0" />
</ItemGroup>

</Project>

Read more

Connecting Windows Media Center to Tvheadend with HDHRProxyIPTV: an alternative to DVBLink

This blog post was updated to use a different method for injecting the channels into the WMC database. The attached tool has been updated accordingly.

After more than 13 years of continuous use, I'm saying goodbye to my traditional Windows Media Center TV setup 😊

Like many (if not most) users, I've always been using Windows Media Center with terrestrial tuners physically attached to my HTPCs:

  • A USB dual-tuner Sony PlayTV when I started playing with WMC back in 2008 (an excellent device that's still working just fine).
  • A PCI dual-tuner Hauppauge WinTV-NOVA-TD-500.
  • A PCIe dual-tuner AVerMedia AVerTV Duo Hybrid (the hardware is good but the driver is terrible and has been responsible for a lot of blue screens...)
  • A PCIe quad-tuner Hauppauge WinTV-quadHD – great hardware and great driver! – when I eventually got tired of the crashes caused by the AVerTV Duo Hybrid.

While this setup certainly lacked the flexibility of more elaborate options based on network tuners (like the popular HDHomeRun) or virtualized tuners such as the now defunct DVBLink, it was actually trivial to set up and exceptionally stable, specially since replacing the old TV tuners by newer Hauppauge WinTV-quadHD cards (these things are not only ultra-stable but they also offer low-latency channel switching and have a fairly good reception).

So, why changing something that has been working so well? It all started with a message posted by a user of the My Digital Life forum – acer-5100 – about using Windows Media Center with H.265/HEVC channels.

As you probably already know, due to internal Windows Media Center/DirectShow limitations, only MPEG1, MPEG2 and H.264 channels are supported and it's not possible to watch or record H.265/HEVC channels, even if you install the appropriate DirectShow codecs. Since WMC was abandoned by Microsoft many years ago, it's extremely unlikely we'll ever see an update to make it compatible with HEVC channels.

To work around this limitation, acer-5100 opted for a simple but clever setup that consists in combining DVBLink (and its IPTV source plugin) with Tvheadend: by simply configuring DVBLink to use transcoded streams provided by Tvheadend rather than the original HEVC sources, Windows Media Center always gets a good old MPEG2 or H.264 video stream it can decode without any issue. Simple and clever.

Read more