This is the third part in a series of posts covering new (and old) features of Duende IdentityServer. These posts are not supposed to be super technical deep dives (that’s what documentation is for), but rather explain the feature at a more conceptual level, why it exists, and why it might useful for you.
The authentication system in ASP.NET Core is designed to be configured at startup time. That’s where you add authentication handlers and their configuration to the DI container. Whenever you need to add a new handler or want to change the configuration, you need to restart the host to re-execute startup.
Also - when a request comes into an ASP.NET Core host, the authentication middleware needs to distinguish between normal requests into your application and protocol callbacks that need to be handled by an authentication handler. For determining this, the middleware needs to ask every configured handler by iterating over them.
The design is not a problem for most scenarios, because you typically have a small(-ish) static list of authentication methods.
If you have the requirement of either being able to adding external authentication methods to your system at runtime, or changing their configuration on-the-fly, this becomes a problem. Also, the little technical detail how the middleware needs to iterate over handlers for every request adds a complexity of O(n) to your pipeline - in other words: the more handlers you have, the more work needs to be done.
We see this requirement very often in federation gateway and SaaS scenarios, where you want to allow your customer to integrate their own authentication system to access your applications - and of course, you do not want to restart your IdentityServer every time this happens.
This is where the built-in configuration system in ASP.NET Core is not optimal - let’s fix this.
Starting with Duende IdentityServer v5.2 we added a new feature to the Enterprise Edition that does (on a high level) the following:
- load authentication handler definitions from a data store on-demand. That allows adding new handlers at any time to the system, and you can update their configuration while the host is running. That is scale-out compatible and has a caching layer built-in.
- by introducing a naming convention for callback URLs, we can optimise the authentication middleware processing and use a dictionary lookup instead of iterating over the full list of handlers. This improves performance when you have a large number of authentication handers configured.
The dynamic loading can co-exist with the standard static authentication handler setup, which means you can statically define some standard handler (e.g. Google) and load others dynamically. We are also only loading the handlers that are really needed, unused handlers do not take up memory space.
To enable this feature, all you need to do is to supply a data store from where IdentityServer can load the configuration from. This could be our standard EntityFramework store, or a custom store.
If you want to learn more about this new feature, here are some links to docs and samples:
As always - feedback is appreciated!