{"id":2891,"date":"2014-07-24T23:12:42","date_gmt":"2014-07-25T06:12:42","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=2891"},"modified":"2014-07-24T23:13:43","modified_gmt":"2014-07-25T06:13:43","slug":"protecting-an-asp-net-webforms-app-with-openid-connect-and-azure-ad","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2014\/07\/24\/protecting-an-asp-net-webforms-app-with-openid-connect-and-azure-ad\/","title":{"rendered":"Protecting an ASP.NET WebForms App with OpenId Connect and Azure AD"},"content":{"rendered":"<p>All of our official .NET samples that show some web UX are based on MVC. This caused somebody to speculate that the new OWIN components for OpenId Connect and WS-Federation require MVC to function. Nothing farther from the true! You can totally use those to secure your WebForms apps. Here there\u2019s a super quick tutorial on how to do it. It is super easy. 98.8% of the tutorial is exactly the same of the corresponding MVC based tutorial, but for the sake of de-normalization I am going to go through those steps by value instead of by reference, on account of the possibility that some of you guys might not have had any previous exposure to this given the samples\u2019 MVC bias.<\/p>\n<h2>Create an empty project<\/h2>\n<p>Fire up the good ol\u2019 VS2013, and head to new project-&gt;ASP.NET Web application. On the project template dialog, pick Web Forms. Hit OK.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/07\/image5.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/07\/image_thumb5.png\" alt=\"image\" width=\"640\" height=\"449\" border=\"0\" \/><\/a><\/p>\n<p>Visual Studio will create your project according to the template you picked. Before moving any further, let\u2019s enable SSL.<\/p>\n<ul>\n<li>Select the project node in solution explorer. Hit F4.<\/li>\n<li>In the resulting property pages, flip SSL Enabled from false to true.<\/li>\n<li>Copy the newly populated SSL URL.<\/li>\n<li>Right click on the project node. Choose properties.<\/li>\n<li>Move to the Web tab. Paste the SSL Url in the Project Url field. Shift+CTR+S to save the new settings.<\/li>\n<\/ul>\n<h2>Provision the app in Azure AD<\/h2>\n<p>Let\u2019s leave VS for few moments and pay a visit to the Azure portal, where we will tell to our Azure AD tenant about our newly minted application.<\/p>\n<p>Navigate to <a title=\"https:\/\/manage.windowsazure.com\/\" href=\"https:\/\/manage.windowsazure.com\/\">https:\/\/manage.windowsazure.com\/<\/a>, sign in as your tenant admin, scroll to the Active Directory tab, choose the tenant you want to use, select the Applications tab, and click the Add button on the appbar at the bottom of the screen.<\/p>\n<p>Choose \u201cAdd an application my organization is developing\u201d.<\/p>\n<p>Give to the app any name you like. Keep the default \u201cweb application and\/or web api\u201d. Click the Next arrow.<\/p>\n<p>In the Sign-On URL enter the HTTPS address you got when you enabled SSL on the project (mine is <a title=\"https:\/\/localhost:44307\/\" href=\"https:\/\/localhost:44307\/\">https:\/\/localhost:44307\/<\/a>). In the App ID URI enter any valid URI that will later remind you of what this app is. For my test app I chose <a title=\"http:\/\/wifeistravellinghenceIblogoutofboredom\" href=\"http:\/\/wifeistravellinghenceIblogoutofboredom\">http:\/\/wifeistravellinghenceIblogoutofboredom<\/a>. Click the Done button.<\/p>\n<p>Click on the Configure tab and leave the browser open there. We\u2019re going to need some of the values here in just a moment.<\/p>\n<h2>Add references to the Cookie\/OpenId Connect\/SystemWeb NuGets<\/h2>\n<p>Next, let\u2019s go back to Visual Studio. Go to Tools-&gt;Library Package Manager-&gt;Package Manager Console. In the console, enter the following three magic commands:<\/p>\n<p><span style=\"font-family: Consolas;\">Install-Package Microsoft.Owin.Security.OpenIdConnect -Pre<\/span><\/p>\n<p><span style=\"font-family: Consolas;\">Install-Package Microsoft.Owin.Security.Cookies \u2013Pre<\/span><\/p>\n<p><span style=\"font-family: Consolas;\">Install-Package Microsoft.Owin.Host.SystemWeb \u2013Pre<\/span><\/p>\n<p>Those will bring down the Katana components you need.<\/p>\n<h2>Add the initialization logic<\/h2>\n<p>We are in good shape! Given that we started from the Individual Auth template, the OWIN pipeline is already present. We just need to change it to use OpenId Connect. If for some reason (e.g ADFS) you want to use WS-Federation, the mechanism is *exactly* the same, you just use the appropriate middleware.<\/p>\n<ul>\n<li>Go to the App_Start folder and open Startup.Auth.cs.<\/li>\n<li>Change the usings directives with the following:<\/li>\n<\/ul>\n<pre class=\"csharpcode\"><span class=\"kwrd\">using<\/span> Microsoft.Owin.Security;\r\n<span class=\"kwrd\">using<\/span> Microsoft.Owin.Security.Cookies;\r\n<span class=\"kwrd\">using<\/span> Microsoft.Owin.Security.OpenIdConnect;\r\n<span class=\"kwrd\">using<\/span> Owin;<\/pre>\n<p>&nbsp;<\/p>\n<ul>\n<li>Next, change the body of ConfigureAuth to match the following:<\/li>\n<\/ul>\n<pre class=\"csharpcode\">app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);\r\n\r\napp.UseCookieAuthentication(<span class=\"kwrd\">new<\/span> CookieAuthenticationOptions());\r\n\r\napp.UseOpenIdConnectAuthentication(\r\n    <span class=\"kwrd\">new<\/span> OpenIdConnectAuthenticationOptions\r\n    {\r\n        ClientId = <span class=\"str\">\"d04fb01f-0715-4ed7-a656-0793b545e1f1\"<\/span>,\r\n        Authority = <span class=\"str\">\"https:\/\/login.windows.net\/6c3d51dd-f0e5-4959-b4ea-a80c4e36fe5e\"<\/span>\r\n    });\r\n<\/pre>\n<p>That will change the pipeline to use OpenId Connect. The values you see there are associated to my test app: you will have to change those with the coordinates of your own app, in your own tenant. Namely:<\/p>\n<ul>\n<li>Go back to the portal. Scroll the app configuration page until you find Client ID. Copy the value. Come back to VS and paste the copied value in the string initializing ClientId<\/li>\n<li>In the string used to initialize Authority, substitute the GUID you see there with the domain of your tenant (e.g. myawesometenant.onmicrosoft.com).<\/li>\n<\/ul>\n<p>Done.<\/p>\n<h2>Give it a spin!<\/h2>\n<p>Hit F5. Your page will come up. Click on the Log In link on the top right corner, which comes directly from the template bits.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/07\/image6.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/07\/image_thumb6.png\" alt=\"image\" width=\"640\" height=\"402\" border=\"0\" \/><\/a><\/p>\n<p>On the right hand side, you\u2019ll notice the OpenIdConnect button. Hit it.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/07\/image7.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/07\/image_thumb7.png\" alt=\"image\" width=\"640\" height=\"433\" border=\"0\" \/><\/a><\/p>\n<p>You\u2019ll see the familiar AAD authentication UX. Enter your test user.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/07\/image8.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/07\/image_thumb8.png\" alt=\"image\" width=\"640\" height=\"105\" border=\"0\" \/><\/a><\/p>\n<p>And voila\u2019! The user is signed in. Q.E.D.<\/p>\n<h2>Extra Credit<\/h2>\n<p>The sequence below does not leave the project in the cleanest possible state \u2013 my goal was to show you in the smallest number of steps that the OpenId Connect (and WSFederation) middleware does work with WebForms.<\/p>\n<p>In a more realistic setup, you would likely start from a template with the \u201cno authentication\u201d option. That would leave you with the responsibility of adding Startup.CS, but that\u2019s really boilerplate code. Also, you would likely want to add some automatic authentication trigger. That is easy enough to achieve. For example, consider the following implementation of Default.aspx.cs:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">using<\/span> Microsoft.Owin.Security;\r\n<span class=\"kwrd\">using<\/span> Microsoft.Owin.Security.OpenIdConnect;\r\n<span class=\"kwrd\">using<\/span> System;\r\n<span class=\"kwrd\">using<\/span> System.Web;\r\n<span class=\"kwrd\">using<\/span> System.Web.UI;\r\n\r\n<span class=\"kwrd\">namespace<\/span> OWINandWebForms\r\n{\r\n    <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">partial<\/span> <span class=\"kwrd\">class<\/span> _Default : Page\r\n    {\r\n        <span class=\"kwrd\">protected<\/span> <span class=\"kwrd\">void<\/span> Page_Load(<span class=\"kwrd\">object<\/span> sender, EventArgs e)\r\n        {\r\n            <span class=\"kwrd\">if<\/span> (!Request.IsAuthenticated)\r\n            {\r\n                HttpContext.Current.GetOwinContext().Authentication.Challenge(\r\n                    <span class=\"kwrd\">new<\/span> AuthenticationProperties { RedirectUri = <span class=\"str\">\"\/\"<\/span> }, \r\n                    OpenIdConnectAuthenticationDefaults.AuthenticationType);\r\n            }\r\n        }\r\n    }\r\n}<\/pre>\n<p>That simply triggers a sign in in case the caller is not authenticated. Not hard at all <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/07\/wlEmoticon-smile4.png\" alt=\"Smile\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Well, there you have it. OpenId Connect, Azure AD and WebForms.<br \/>\nWe chose OWIN as the platform for our new wave of identity libraries because of its flexibility \u2013 don\u2019t let the fact that we standardized on MVC for our samples stop you from enjoying the latest and greatest <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2014\/07\/wlEmoticon-smile4.png\" alt=\"Smile\" \/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>All of our official .NET samples that show some web UX are based on MVC. This caused somebody to speculate that the new OWIN components for OpenId Connect and WS-Federation require MVC to function. Nothing farther from the true! You can totally use those to secure your WebForms apps. Here there\u2019s a super&#8230;<\/p>\n","protected":false},"author":1,"featured_media":2885,"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-2891","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2891","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=2891"}],"version-history":[{"count":2,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2891\/revisions"}],"predecessor-version":[{"id":2894,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/2891\/revisions\/2894"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/2885"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=2891"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=2891"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=2891"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}