Adding OpenIddict 3.0 to an OWIN application

Up-to-date samples for ASP.NET 4.x and OWIN can be found in the openiddict/openiddict-samples repository:

  • Fornax: authorization code flow demo using ASP.NET Web Forms 4.8 and OWIN/Katana, with a .NET console acting as the client.
  • Kalarba: resource owner password credentials demo using OWIN/Katana, ASP.NET Web API and the OpenIddict degraded mode.

Last year, I announced that OpenIddict would become compatible with OWIN/Katana – and thus usable in any ASP.NET 4.x non-Core application – as part of the 3.0 release. While using OpenIddict in an OWIN application shouldn't be much different than using it in an ASP.NET Core application, there's actually a part than will slightly differ between the two platforms: dependency injection.

Globally introduced in ASP.NET Core 1.0, dependency injection support was not a thing in OWIN. Yet, OpenIddict itself depends on dependency injection for all its features: core, server and token validation. To work around the lack of official DI support, OpenIddict 3.0 will support two approaches: one working with the Autofac DI container and one without. This blog post briefly describes how to do that.

To keep things simple, we'll create a tiny self-hosted .NET 4.7.2 OWIN application, but of course, these 2 approaches also work in any ASP.NET application, no matter what's the host used: HttpListener, System.Web or even third-party options like Nowin.

For that, create a new application with the following .csproj, that contains the basic things we'll need: the Microsoft DI primitives used by OpenIddict, the OWIN self-host and hosting abstractions and the OpenIddict OWIN metapackage (that itself references the core, server and validation packages, plus the OWIN integration assembly):

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

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net472</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.4" />
<PackageReference Include="Microsoft.Owin.Host.HttpListener" Version="4.1.0" />
<PackageReference Include="Microsoft.Owin.Hosting" Version="4.1.0" />
<PackageReference Include="OpenIddict.Owin" Version="3.0.0-beta1.20311.67" />
</ItemGroup>

</Project>

Read more

Creating an OpenID Connect server proxy with OpenIddict 3.0's degraded mode

As some of you may already know, I've been working on OpenIddict 3.0 for a few months now. One of the main goals of this major release is to merge ASOS (a low-level OpenID Connect server middleware for ASP.NET Core) and OpenIddict (a higher-level OIDC server library designed for less advanced users) into a unified code base, that would ideally represent the best of both worlds.

As part of this task, a new feature was added to OpenIddict: the degraded mode (also known as the ASOS-like or bare mode). Put simply, this mode allows using OpenIddict's server without any backing database. Once enabled, all the features that rely on the OpenIddict application, authorization, scope and token managers (contained in the OpenIddict.Core package) are automatically disabled, which includes things like client_id/client_secret or redirect_uri validation, reference tokens and token revocation support. In other words, this mode allows switching from an "all you can eat" offer to a "pay-to-play" approach.

A thread, posted on one of the aspnet-contrib repositories gave me a perfect opportunity to showcase this particular feature. The question asked by the commenters was simple: how can I use an external authentication provider like Steam (that implements the legacy OpenID 2.0 protocol) with my own API endpoints?

Steam doesn't issue any access token you could directly use with your API endpoints. Actually, access tokens are not even a thing in OpenID 2.0, which is a pure authentication protocol that doesn't offer any authorization capability (unlike OAuth 1.0/2.0 or OpenID Connect).

So, how do we solve this problem? The most common approach typically consists in creating your own authorization server between your frontend application and the remote authentication provider (here, Steam). This way, when the application needs to authenticate a user, the user is redirected to the authorization server, that delegates the actual authentication part to another party. Once authenticated by that party, the user is redirected back to the main authorization server, that issues an access token to the client application.

This a super common scenario, that can be implemented using standard protocols like OpenID Connect and well-known implementations like OpenIddict or IdentityServer. However, these options are sometimes considered "overkill" for such simple scenarios. After all, why would you need a fully-fledged OIDC server – with login, registration or consent views – when all you want is to delegate the actual authentication to another server in a totally transparent and almost invisible way?

Rolling your own protocol is tempting... but a very bad idea, as you can't benefit from all the security measures offered by standard flows like OAuth 2.0/OpenID Connect's authorization code flow, whose threat model is clearly identified for many years now. As you may have guessed by now, this is precisely where OpenIddict 3.0's degraded mode can come in handy.

Read more

Forcing an old .NET application to support TLS 1.2 without recompiling it

As most servers are moving toward TLS 1.3 and removing TLS 1.0/1.1 support, examples of legacy .NET applications – compiled with an old version of the .NET Framework, like 4.0 or 4.5 – experiencing connectivity issues with TLS 1.2 servers are becoming more and more common, specially since installing a more recent version of the .NET Framework is not sufficient: it's the version used for compiling your project that actually matters when it comes to selecting the supported TLS versions during the TLS handshake.

To make migration a bit less painful, Microsoft published a "transport security best practices" paper that list a few solutions that help avoid handshake errors related to the use of legacy TLS versions that are no longer considered safe.

One of the proposed solutions is to update your project to target .NET Framework 4.7: in this case, you'll have nothing else to do, as .NET 4.7 applications automatically default to whatever the operating system they run on offers and considers safe (which currently includes TLS 1.2 and will later include TLS 1.3).

Unfortunately, such an option requires re-compiling the application, which is not always feasible. Thankfully, you can also force an existing application to use the system default TLS versions without having to re-compile it (assuming it doesn't explicitly set the SSL/TLS versions it prefers via ServicePointManager).

The best practices paper lists a few options, but my favourite one is the one that consists in simply updating the configuration file associated with the application executable, as it's easy to do and doesn't impact anything else on the machine.

For that, locate the configuration file associated to the executable of the application you want to add TLS 1.2 support to: it's always named [name of the executable].exe.config. If there's no such file, create one. Once located or created, update its content to enable the compatibility switch required to support TLS 1.2:

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<AppContextSwitchOverrides value="Switch.System.Net.DontEnableSystemDefaultTlsVersions=false"/>
</runtime>
</configuration>

If you're still using Windows 7, you'll also have to tweak the registry to enable TLS 1.2 support, as indicated on https://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings.

OpenIddict 1.0 and 2.0 general availability

I'm very happy to announce that OpenIddict 1.0 and 2.0 final packages were pushed earlier today to NuGet.org and are now officially available!

What changed new since RC3?

A security bug was fixed

A few days ago, a vulnerability impacting application permissions was publicly reported by nurhat on GitHub (many thanks to him!).

In a nutshell, scope permissions were not correctly enforced for public clients using the password flow and custom grant types (confidential clients or clients using the code or client credentials flows were not impacted).

A fix was immediately added to the nightly builds and is present in the RTM release.

Built-in entity caches are now included

OpenIddict now comes with built-in entity caching to avoid having to send multiple requests to retrieve the same entities. Concretely, if your AuthorizationController uses APIs like OpenIddictApplicationManager.FindByClientIdAsync(request.ClientId), the corresponding application will be directly retrieved from the cache and the resulting operation will be extremely cheap.

To ensure this feature works with non-thread-safe stores and stores that rely on context-affinity (like Entity Framework 6.x or Entity Framework Core), these built-in caches are scoped so that cached entities are not reused across requests.

While definitely not recommended, this feature can be disabled via the OpenIddict core options:

1
2
3
4
5
6
7
services.AddOpenIddict()
.AddCore(options =>
{
// ...

options.DisableEntityCaching();
})

Read more

Highway to (DLL) Hell

It's no secret that I've always been a huge fan of Windows Media Center, probably the best digital/personal video recorder out there and definitely one of the most impressive Microsoft applications developed using the .NET Framework.

As an avid WMC user, I have built 3 HTPC machines and recorded thousands of TV programs (movies, series, documentaries, etc.). As such, when Microsoft announced in May 2015 that Windows Media Center would no longer be developed (almost 6 year after disbanding the development team!) – and thus would not be part of Windows 10 – I refused to migrate to Windows 10, despite Microsoft's offers encouraging users to upgrade their OS for free.

The fact Windows Media Center was not available on Windows 10 – even as a paid feature like it was on Windows 8.x – was a major blocker for many users. To work around this limitation, enthusiasts decided to create an unofficial port of Windows Media Center for Windows 10.

While unofficial, the port worked just fine. But over time, Microsoft started to update some of the system components Windows Media Center relied on, causing annoying bugs. For instance, the introduction of breaking changes in Windows 10 1803 made watching a .wtv file (WMC's TV file format) recorded on Windows 7 completely impossible.

While investigating, I discovered that the issue was caused by a change in MSVidCtl.dll, the system-wide DLL containing the DirectShow components needed by WMC for all its TV-related features. After replacing the faulty DLL by an older version, WMC was able to play old recordings like a charm.

This phenomenom, that occurs every time API or functional changes are introduced in a DLL a program depends on, has a name: DLL Hell.

Read more