Earlier this month, Barry Dorrans – the Security PM for .NET – announced that the ASP.NET Core templates would be updated to target Duende IdentityServer5 as part of the .NET 6 effort and that the ASP.NET team was considering creating a development-only tool for testing OpenID Connect integration in .NET 7.
By looking at the reactions under the blog post, on GitHub or on Reddit, the least we can say is that people are always quite passionate when it comes to how Microsoft treats these topics. Some like that decision while a few others feel "betrayed" and consider this move a "bait and switch":
Despite this move, my personal opinion hasn't changed: I was very happy when Microsoft announced they would use IdentityServer4 in 2018 and the commitment to use the new dual-licensed version of IdentityServer in .NET 6 (instead of writing their own OIDC server from scratch) is, in my opinion, a step in the right direction in changing their relationship with the .NET community: Microsoft can't provide everything out-of-the-box and promoting third-party projects is a great approach.
The fact Microsoft keeps sponsoring the IdentityServer project – for $12,000/year at the time of writing – is also an excellent signal sent to the community. Even if you've never liked Microsoft's love/hate relationship with OSS, it would be very hard to deny that the company has positively changed in this regard.
That said, I'd be lying if I didn't admit I was quite disappointed when reading that blog post: OpenIddict – the OpenID Connect server I maintain – wasn't even mentioned as a potential free and open source alternative that can be used on-premises or hosted in a cloud application.
This omission is not an oversight: Barry and the rest of the ASP.NET team know my work and we informally discussed potential options that could have helped secure their supply chain, should they have included something based on OpenIddict in the ASP.NET templates: even options like making OpenIddict a co-owned project were on the table.
This omission has a reason, clearly explained in the blog post: Microsoft wants you to use their cloud offers: Azure AD and Azure AD B2C. In fact, the ASP.NET team is already working on migration guides to help users move to Azure AD as part of their .NET 6 effort (fun fact: the thread has been locked so that only members of the .NET team can reply).
The crucial thing to note here is that Azure AD – or the equivalents offered by Okta, Auth0, Firebase or Amazon – are not just OpenID Connect servers like IdentityServer or OpenIddict (that typically rely on a membership stack like ASP.NET Core Identity): they also aim at replacing your users database.
Relying on a SaaS product to take care of your users database is not a bad idea in itself: most of the security aspects are managed for you by the cloud vendors, that will transparently maintain the software and hardware, keep your users database safe and try their best to protect your application against bad actors. This argument alone is often enough to justify the move to cloud solutions like Azure AD:
Microsoft already has a team and a product in that area, Azure Active Directory, which allows 500,000 objects for free. The ASP.NET team feels a managed cloud solution remains the best practical option for developers – the security is managed, you don’t store credentials locally with the risks that presents.
After all, Azure AD has a free plan with up to 500,000 users (*), so this should be a no-brainer, right? Not so fast: these services are always free for a reason: their business model relies on the fact a fraction of their customers will end up exceeding the limits of the free plan. At that point, customers basically have three options:
- Remove as many users as needed to avoid reaching the limit (e.g by removing "inactive" accounts, but this typically only works for a while).
- Pay for the service. At the time of writing, Microsoft charges an insanely high $6/user rate for those on a paid plan.
- Move to a different vendor with a different pricing model.
The thing is moving to a different vendor is never an easy task as cloud vendors typically do their best to make that a difficult process: while you're generally allowed to export non-sensitive parts of your users database (e.g to re-import it in a different service), there's a thing you often have no control over: password hashes:
- Azure AD and Okta don't allow you to retrieve them. In practice, this means you'll need to reset all your user passwords, which is generally horrible from a user experience perspective.
- Auth0 offers an option to export users with their passwords, but this requires contacting the support. To deter you from doing that, their documentation explicitly says that "they are unable to accept or guarantee requests for exports at a specific time and date". Oh and guess what? It's not possible if you're on a free plan! And now that Auth0 was acquired by Okta for $6,5B, who knows how long this ability will stay?
While cloud-based identity offers are captive environments, things are completely different with IdentityServer and OpenIddict, that are often used in conjunction with ASP.NET Core Identity: you own the database and user passwords are stored in a format that could even be implemented in a non-.NET environment (after all, it uses PBKDF under the hood).
When using an open-source solution you can run locally, you have full control over your data. With a cloud offer, the story is completely different. Don't get lured by free plans: if you're interested in a cloud offer, make sure the pricing model of paid plans is adequate for your case before even considering it (and even then, be prepared for a potential price increase at any point).
(*) Actually, the free plan's limit is 50,000 objects. If you need additional entries, you have to ask the Azure support to extend the limit, which is something they do at their own discretion.