Auto-Update of the Signing Keys via Metadata
Quite a mouthful, isn’t it
TL;DR version: we just released an update to the ValidatingIssuerNameRegistry which makes it easy for you to write applications that automatically keep up to date the WIF settings containing the keys that should be used to validate incoming tokens.
The Identity and Access Tools for Visual Studio 2012 will pick up the new version automatically, no action required for you.
The Validation Mechanism in WIF’s Config
When you run the Identity and Access Tool for VS2012 (or the ASP.NET Tools for Windows Azure AD) you can take advantage of the metadata document describing the authority you want to trust to automatically configure your application to connect to it. In practice, the tool adds various WIF-related sections in your web.config; those are used for driving the authentication flow.
One of those elements, the <issuerNameRegistry>, is used to keep track of the validation coordinates that must be used to verify incoming tokens; below there’s an example.
<issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry,
System.IdentityModel.Tokens.ValidatingIssuerNameRegistry"> <authority name="https://lefederateur.accesscontrol.windows.net/"> <keys> <add thumbprint="C1677FBE7BDD6B131745E900E3B6764B4895A226" /> </keys> <validIssuers> <add name="https://lefederateur.accesscontrol.windows.net/" /> </validIssuers> </authority> </issuerNameRegistry>
The key elements here are the keys (a collection of thumbprints indicating which certificates should be used to check the signature of incoming tokens) and the validIssuers (list of names that are considered acceptable values for the Issuer element of the incoming tokens (or equivalent in non-SAML tokens)).
That’s extremely handy (have you ever copied thumbprints by hand? I did, back in the day) however that’s not a license for forgetting about the issuer’s settings. What gets captured in config is just a snapshot of the current state of the authority, but there’s no guarantee that things won’t change in the future. In fact, it is actually good practice for an authority to occasionally roll keys over.
If a key rolls, and you don’t re-run the tool to update your config accordingly, your app will now actively refuse the tokens signed with the new key; your users will be locked out. Not good.
Dynamically Update of the Issuer Coordinates in Web.Config
WIF includes fairly comprehensive metadata manipulation API support, which you can use for setting up your own config auto-refresh; however it defaults to the in-box implementation of IssuerNameRegistry, ConfigBasedIssuerNameRegistry, and in this post I made clear that ValidatingIssuerNameRegistry has clear advantages over the in-box class. We didn’t want you to have to choose between easy config refresh and correct validation logic, hence we updated ValidatingIssuerNameRegistry to give you both
In a nutshell, we added a new static method (WriteToConfig) which reads a metadata document and, if it detects changes, it updates an <issuerNamerRegistry> in the web.config to reflect what’s published in metadata. Super-easy!
I would suggest invoking that method every time your application starts: that happens pretty often if you use the IIS defaults, and it is a safe time to update the web.config without triggering unwanted recycles. For example, here there’s how your global.asax might look like:
using System; using System.Web.Http; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; using System.Configuration; using System.IdentityModel.Tokens; namespace MvcNewVINR { public class MvcApplication : System.Web.HttpApplication {
protected void RefreshValidationSettings() { string configPath =
AppDomain.CurrentDomain.BaseDirectory + "\\" + "Web.config"; string metadataAddress =
ConfigurationManager.AppSettings["ida:FederationMetadataLocation"]; ValidatingIssuerNameRegistry.WriteToConfig(metadataAddress, configPath); } protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); RefreshValidationSettings(); } } }
..and that’s it
We also added another method, GetIssuingAuthority, which returns the authority coordinates it read without committing them to the config: this comes in handy when you overwrote ValidatingIssuerNameRegistry to use your custom logic, issuers repository, etc and you want to write down the info in your own custom schema.
Self-healing of the issuer coordinates is a great feature, and I would recommend you consider it for all your apps: especially now that it’s really easy to set up
This whole new ValidatingIssuerNameRegistry release comes just in time for my current project! Thanks for getting this out.
I’m just not sure of the real use case for the WriteToConfig method. You suggest that we can update the web.config during application startup, but doesn’t this requires the AppPool process’ identity to have write privileges on the web.config file, which I guess is something that never happens?
It does occasionally happen 😉 for example, Windows Azure Web Sites today appear to support it.
In any case, if you prefer an off-the-config solution, please check out http://msdn.microsoft.com/en-us/library/windowsazure/dn151789.aspx
HTH!
V.