{"id":2012,"date":"2013-04-02T09:41:05","date_gmt":"2013-04-02T18:41:05","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=2012"},"modified":"2013-04-02T09:41:05","modified_gmt":"2013-04-02T18:41:05","slug":"auto-update-of-the-signing-keys-via-metadata","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2013\/04\/02\/auto-update-of-the-signing-keys-via-metadata\/","title":{"rendered":"Auto-Update of the Signing Keys via Metadata"},"content":{"rendered":"<p>Quite a mouthful, isn\u2019t it <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/04\/wlEmoticon-smile.png\"><\/p>\n<p><strong>TL;DR version<\/strong>: we just released an update to the <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/02\/08\/multitenant-sts-and-token-validation-4\/\">ValidatingIssuerNameRegistry<\/a> 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.<br \/>The <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/03\/25\/a-refresh-of-the-identity-and-access-tool-for-vs-2012\/\">Identity and Access Tools for Visual Studio 2012<\/a> will pick up the new version automatically, no action required for you.<\/p>\n<h2>The Validation Mechanism in WIF\u2019s Config <\/h2>\n<p>When you run the <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/03\/25\/a-refresh-of-the-identity-and-access-tool-for-vs-2012\/\">Identity and Access Tool for VS2012<\/a> (or the <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/02\/18\/microsoft-asp-net-tools-for-windows-azure-active-directory-visual-studio-2012-4\/\">ASP.NET Tools for Windows Azure AD<\/a>) 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.<br \/>One of those elements, the &lt;issuerNameRegistry&gt;, is used to keep track of the validation coordinates that must be used to verify incoming tokens; below there\u2019s an example.<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">&lt;<\/span><span class=\"html\">issuerNameRegistry<\/span> <span class=\"attr\">type<\/span><span class=\"kwrd\">=\"System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, <\/span><\/pre>\n<pre class=\"csharpcode\"><span class=\"kwrd\">                          System.IdentityModel.Tokens.ValidatingIssuerNameRegistry\"<\/span><span class=\"kwrd\">&gt;<\/span>\n  <span class=\"kwrd\">&lt;<\/span><span class=\"html\">authority<\/span> <span class=\"attr\">name<\/span><span class=\"kwrd\">=\"https:\/\/lefederateur.accesscontrol.windows.net\/\"<\/span><span class=\"kwrd\">&gt;<\/span>\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">keys<\/span><span class=\"kwrd\">&gt;<\/span>\n      <span class=\"kwrd\">&lt;<\/span><span class=\"html\">add<\/span> <span class=\"attr\">thumbprint<\/span><span class=\"kwrd\">=\"C1677FBE7BDD6B131745E900E3B6764B4895A226\"<\/span> <span class=\"kwrd\">\/&gt;<\/span>\n    <span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">keys<\/span><span class=\"kwrd\">&gt;<\/span>\n    <span class=\"kwrd\">&lt;<\/span><span class=\"html\">validIssuers<\/span><span class=\"kwrd\">&gt;<\/span>\n      <span class=\"kwrd\">&lt;<\/span><span class=\"html\">add<\/span> <span class=\"attr\">name<\/span><span class=\"kwrd\">=\"https:\/\/lefederateur.accesscontrol.windows.net\/\"<\/span> <span class=\"kwrd\">\/&gt;<\/span>\n    <span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">validIssuers<\/span><span class=\"kwrd\">&gt;<\/span>\n  <span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">authority<\/span><span class=\"kwrd\">&gt;<\/span>\n<span class=\"kwrd\">&lt;\/<\/span><span class=\"html\">issuerNameRegistry<\/span><span class=\"kwrd\">&gt;<\/span>\n<\/pre>\n<style type=\"text\/css\">.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }\n<\/style>\n<p>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)).<\/p>\n<p>That\u2019s extremely handy (have you ever copied thumbprints by hand? I did, back in the day) however that\u2019s not a license for forgetting about the issuer\u2019s settings. What gets captured in config is just a snapshot of the current state of the authority, but there\u2019s no guarantee that things won\u2019t change in the future. In fact, it is actually good practice for an authority to occasionally roll keys over.<\/p>\n<p>If a key rolls, and you don\u2019t 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.<\/p>\n<h2>Dynamically Update of the Issuer Coordinates in Web.Config<\/h2>\n<p>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&nbsp; IssuerNameRegistry, ConfigBasedIssuerNameRegistry, and in <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/02\/08\/multitenant-sts-and-token-validation-4\/\">this post<\/a> I made clear that ValidatingIssuerNameRegistry has clear advantages over the in-box class. We didn\u2019t want you to have to choose between easy config refresh and correct validation logic, hence we updated ValidatingIssuerNameRegistry to give you both <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/04\/wlEmoticon-smile.png\"><\/p>\n<p>In a nutshell, we added a new static method (WriteToConfig) which reads a metadata document and, if it detects changes, it updates an &lt;issuerNamerRegistry&gt; in the web.config to reflect what\u2019s published in metadata. Super-easy!<\/p>\n<p>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\u2019s how your global.asax might look like:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">using<\/span> System;\n<span class=\"kwrd\">using<\/span> System.Web.Http;\n<span class=\"kwrd\">using<\/span> System.Web.Mvc;\n<span class=\"kwrd\">using<\/span> System.Web.Optimization;\n<span class=\"kwrd\">using<\/span> System.Web.Routing;\n<span class=\"kwrd\">using<\/span> System.Configuration;\n<span class=\"kwrd\">using<\/span> System.IdentityModel.Tokens;\n\n<span class=\"kwrd\">namespace<\/span> MvcNewVINR\n{\n    <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">class<\/span> MvcApplication : System.Web.HttpApplication\n    {<br>        <strong><span class=\"kwrd\">protected<\/span> <span class=\"kwrd\">void<\/span> RefreshValidationSettings()\n        {\n            <span class=\"kwrd\">string<\/span> configPath = <\/strong><\/pre>\n<pre class=\"csharpcode\"><strong>              AppDomain.CurrentDomain.BaseDirectory + <span class=\"str\">\"\\\\\" + \"<\/span>Web.config<\/strong><span class=\"str\"><strong>\";\n            string metadataAddress = <\/strong><\/span><\/pre>\n<pre class=\"csharpcode\"><strong><span class=\"str\">              ConfigurationManager.AppSettings[\"<\/span>ida:FederationMetadataLocation\"];\n            ValidatingIssuerNameRegistry.WriteToConfig(metadataAddress, configPath);\n        }\n<\/strong>        <span class=\"kwrd\">protected<\/span> <span class=\"kwrd\">void<\/span> Application_Start()\n        {\n            AreaRegistration.RegisterAllAreas();\n            WebApiConfig.Register(GlobalConfiguration.Configuration);\n            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);\n            RouteConfig.RegisterRoutes(RouteTable.Routes);\n            BundleConfig.RegisterBundles(BundleTable.Bundles);\n            <strong>RefreshValidationSettings();<\/strong>\n        }\n    }\n}<\/pre>\n<style type=\"text\/css\">.csharpcode, .csharpcode pre\n{\n\tfont-size: small;\n\tcolor: black;\n\tfont-family: consolas, \"Courier New\", courier, monospace;\n\tbackground-color: #ffffff;\n\t\/*white-space: pre;*\/\n}\n.csharpcode pre { margin: 0em; }\n.csharpcode .rem { color: #008000; }\n.csharpcode .kwrd { color: #0000ff; }\n.csharpcode .str { color: #006080; }\n.csharpcode .op { color: #0000c0; }\n.csharpcode .preproc { color: #cc6633; }\n.csharpcode .asp { background-color: #ffff00; }\n.csharpcode .html { color: #800000; }\n.csharpcode .attr { color: #ff0000; }\n.csharpcode .alt \n{\n\tbackground-color: #f4f4f4;\n\twidth: 100%;\n\tmargin: 0em;\n}\n.csharpcode .lnum { color: #606060; }\n<\/style>\n<p>..and that\u2019s it <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/04\/wlEmoticon-smile.png\"><\/p>\n<p>We also added another method,&nbsp; GetIssuingAuthority, which returns the authority coordinates it read without committing them to the config: this comes in handy when you overwrote <a href=\"https:\/\/www.cloudidentity.com\/blog\/2013\/02\/08\/multitenant-sts-and-token-validation-4\/\">ValidatingIssuerNameRegistry<\/a> to use your custom logic, issuers repository, etc and you want to write down the info in your own custom schema.<\/p>\n<p>&nbsp;<\/p>\n<p>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\u2019s really easy to set up <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none\" alt=\"Smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2013\/04\/wlEmoticon-smile.png\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Quite a mouthful, isn\u2019t 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&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2012","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2012","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/comments?post=2012"}],"version-history":[{"count":0,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2012\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=2012"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=2012"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=2012"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}