{"id":35045,"date":"2019-02-20T12:36:32","date_gmt":"2019-02-20T19:36:32","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/premier-developer\/?p=35045"},"modified":"2019-02-18T14:28:59","modified_gmt":"2019-02-18T21:28:59","slug":"convert-asp-net-webforms-with-windows-authentication-to-use-aad","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/premier-developer\/convert-asp-net-webforms-with-windows-authentication-to-use-aad\/","title":{"rendered":"Convert ASP.NET WebForms with Windows Authentication to use AAD"},"content":{"rendered":"<p><span style=\"float: none;background-color: #ffffff;color: #333333;font-family: Segoe UI,'Segoe UI Web Regular','Segoe UI Regular WestEuropean','Segoe UI',Tahoma,Arial,Roboto,'Helvetica Neue',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size: 16.93px;font-style: normal;font-variant: normal;font-weight: 400;letter-spacing: normal;text-align: left;text-decoration: none;text-indent: 0px\">App Dev Manager <\/span><a class=\"x-hidden-focus\" href=\"https:\/\/www.linkedin.com\/in\/christopher-westbrook-a34a268a\/\">Chris Westbrook<\/a> tackles the topic of moving legacy ASP.NET Web Forms using integrated authentication to Azure.<\/p>\n<hr \/>\n<h2>Introduction \/ Goal<\/h2>\n<p>In this post we\u2019re going to walk through updating an ASP.NET Web Forms application to use Azure Active Directory (AAD). Yes, you read that right, Web Forms. Why would we cover such an old tech you ask? I work with a lot of enterprise customers that have sizable portfolios of Intranet web sites using Web Forms and Windows Integrated Authentication that they would like to move to Azure PaaS; however, we\u2019ve found that a lot of documentation on these topics doesn\u2019t extend back to Web Forms and instead targets .NET Core and MVC. Although I do encourage my customers to consider a rebuild, that may not be feasible. Therefore, this post walks through some relatively minor tweaks that allow you to switch your site to use AAD for authentication and, if you want, AD group membership for authorization. These changes will enable deployment of those sites to Azure App Services.<\/p>\n<p>To make the change we\u2019re going to follow the below steps:<\/p>\n<ol>\n<li>Start with an ASP.NET Web Forms site and some other pre-requisites<\/li>\n<li>Ensure your site is setup to use SSL.<\/li>\n<li>Get the necessary OWIN NuGet packages.<\/li>\n<li>Add in some startup code to use the OWIN authentication libraries.<\/li>\n<li>Register your application in AAD.<\/li>\n<li>Update your web.config with appropriate OAuth values.<\/li>\n<li>Test.<\/li>\n<\/ol>\n<h2>Pre-requisites<\/h2>\n<p>Here are some assumptions I\u2019m making as to the starting point for this article:<\/p>\n<ul>\n<li>You have an existing ASP.NET Web Forms application deployed on an on-premise IIS server.\n<ul>\n<li>Or you\u2019re going to make a new one to test on. (See first step below.)<\/li>\n<\/ul>\n<\/li>\n<li>The site is configured to use Windows Authentication.<\/li>\n<li>The site uses AD groups for authorization.<\/li>\n<li>You already have an Azure Active Directory setup with the users and groups that you need.\n<ul>\n<li>Typically, enterprises get this when they adopt Office 365, but that\u2019s not the only way. You can also create a new AAD for this.<\/li>\n<\/ul>\n<\/li>\n<li>You have identified at least two AD groups to use to test membership checking.\n<ul>\n<li>Pick one you know you are in and one you know you are not in.<\/li>\n<\/ul>\n<\/li>\n<li>You\u2019re using Visual Studio 2017.\n<ul>\n<li>I\u2019ll be using v15.9.3.<\/li>\n<\/ul>\n<\/li>\n<li>You\u2019ve already upgraded to a recent .NET framework.\n<ul>\n<li>I\u2019ll be using 4.7.2. I\u2019ve also done this with 4.6.2 but I haven\u2019t researched the earliest version you could use.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2>Step 1: ASP.NET Web Forms Site<\/h2>\n<p>For demo purposes I\u2019m going to start with a new site from the Visual Studio template. You may want to do the same to start with. Eventually though you\u2019ll want to reproduce this on your actual site, in which case you\u2019ll skip this step. If you\u2019re not familiar with this process you can see the tutorial at <a href=\"https:\/\/docs.microsoft.com\/en-us\/aspnet\/web-forms\/overview\/getting-started\/creating-a-basic-web-forms-page\">https:\/\/docs.microsoft.com\/en-us\/aspnet\/web-forms\/overview\/getting-started\/creating-a-basic-web-forms-page<\/a>. I named my project \u201cWindowsAuthAppToAADDemo.\u201d Be sure to change the Authentication mechanism to Windows Authentication as that\u2019s the scenario we\u2019re working with.<\/p>\n<p>It will also be helpful to place some code on one of your pages that you can use to test. One possibility is to add some code like below to About.aspx:<\/p>\n<p><code>&lt;dl&gt; <\/code>\n<code>&lt;dt&gt;IsAuthenticated&lt;\/dt&gt; <\/code>\n<code>&lt;dd&gt;&lt;%= HttpContext.Current.User.Identity.IsAuthenticated %&gt;&lt;\/dd&gt; <\/code>\n<code>&lt;dt&gt;AuthenticationType&lt;\/dt&gt; <\/code>\n<code>&lt;dd&gt;&lt;%= HttpContext.Current.User.Identity.AuthenticationType %&gt;&lt;\/dd&gt; <\/code>\n<code>&lt;dt&gt;Name&lt;\/dt&gt; <\/code>\n<code>&lt;dd&gt;&lt;%= HttpContext.Current.User.Identity.Name %&gt;&lt;\/dd&gt; <\/code>\n<code>&lt;dt&gt;Is in \"group1\"&lt;\/dt&gt; <\/code>\n<code>&lt;dd&gt;&lt;%= HttpContext.Current.User.IsInRole(\"yourgroup1here\") %&gt;&lt;\/dd&gt; <\/code>\n<code>&lt;dt&gt;Is in \"group2\"&lt;\/dt&gt; <\/code>\n<code>&lt;dd&gt;&lt;%= HttpContext.Current.User.IsInRole(\"yourgroup2here\") %&gt;&lt;\/dd&gt; <\/code>\n<code>&lt;dl&gt;<\/code><\/p>\n<p>To make sure things are working this is a good time to run your project and navigate to the About page. Make sure you see True for IsAuthenticated, your domain\\login for Name, and the appropriate true\/false values for your group membership.<\/p>\n<h2>Step 2: SSL<\/h2>\n<p>When you\u2019re using AAD you will be using OAuth. This process requires the use of SSL to be secure. Therefore, even in your local development environment, you\u2019re going to need to use SSL. I\u2019m using IIS Express, so I just used the properties pane of the web project to set SSL Enabled to true. Also make a note of your new URL with the auto-assigned port. You can find this in the web project Properties page, Web tab, Project Url field. Make sure to run and verify the site now opens using SSL.<\/p>\n<h2>Step 3: OWIN Packages via NuGet<\/h2>\n<p>Even though OWIN probably didn\u2019t exist back when you wrote your Web Forms app, you can still use it and it will significantly simplify the process.<\/p>\n<ol>\n<li>In the Visual Studio menu, select <strong>Tools <\/strong>&gt; <strong>NuGet Package Manager <\/strong>&gt; <strong>Package Manager Console<\/strong>.<\/li>\n<li>Make sure your web project is selected in the <strong>Default project<\/strong> drop down.<\/li>\n<li>Run the below commands:\ninstall-package Microsoft.Owin.Host.SystemWeb\ninstall-package Microsoft.Owin.Security.OpenIdConnect\ninstall-package Microsoft.Owin.Security.Cookies<\/li>\n<\/ol>\n<p>You can do a build to make sure nothing has gone awry yet. However, if you try to run you will get errors at this point. We need to continue with the next steps.<\/p>\n<h2>Step 4: Add Startup Authentication Code<\/h2>\n<p>Next, we need to add some code to the OWIN startup process and adjust the web.config. I have sample code shared in this gist: <a href=\"https:\/\/gist.github.com\/cmw2\/6a537a4bfa6636f8221a7fc572197988\">https:\/\/gist.github.com\/cmw2\/6a537a4bfa6636f8221a7fc572197988<\/a> which is discussed below:<\/p>\n<ol>\n<li>In your App_Start Folder, create a StartupAuth.cs file and replace its contents with what\u2019s shown in the gist. Adjust namespace to match your project.<\/li>\n<li>In your main\/root folder create a Startup.cs file and replace its contents again with what\u2019s shown in the gist which is just calling the ConfigureAuth method from the above step. Or you can just add the call if you already have a Startup class doing other things.<\/li>\n<li>In your web.config we\u2019ll need to turn off Windows Authentication, remove FormsAuthentication, and add appSettings values that are used by the above code. Again, you can see the details in the gist.<\/li>\n<\/ol>\n<p>At this point you should be able to build with no compilation errors, but you still can\u2019t run.<\/p>\n<h2>Step 5: Register your application in AAD<\/h2>\n<p>Now we need to register your application with your AAD.<\/p>\n<ol>\n<li>First follow the steps outlined in the docs here: <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/active-directory\/develop\/quickstart-register-app\">https:\/\/docs.microsoft.com\/en-us\/azure\/active-directory\/develop\/quickstart-register-app<\/a> to create your registration.<\/li>\n<\/ol>\n<p style=\"padding-left: 60px\">For Redirect URI, use your local dev environment SSL URL. For my registration I used:<\/p>\n<p style=\"padding-left: 60px\">Name: WindowsAuthAppToAADDemo\nSupported Account Types: Accounts in this organizational directory only\nRedirect URI: Web, https:\/\/localhost:44356\/ (yours will be different)<\/p>\n<ol>\n<li>Next let\u2019s make sure it is configured to return ID tokens that our app will use to read information about the logged in user. In the left-hand blade menu for your registration,\n<ol>\n<li>Click <strong>Authentication<\/strong><\/li>\n<li>Under <strong>Advanced Settings<\/strong> check <strong>ID tokens.<\/strong><\/li>\n<li>Click <strong>Save<\/strong><\/li>\n<\/ol>\n<\/li>\n<li>Finally, let\u2019s make sure group membership is a part of our token. In the left hand blade menu for your registration, click <strong>Manifest<\/strong>, then\n<ol>\n<li>Find: &#8220;groupMembershipClaims&#8221;: null,<\/li>\n<li>And change to: &#8220;groupMembershipClaims&#8221;: &#8220;SecurityGroup&#8221;,<\/li>\n<li>Click <strong>Save<\/strong><\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<h2>Step 6: Update your web.config with appropriate OAuth values<\/h2>\n<p>From the Overview page of your app registration you\u2019ll see some values that you can paste into the web.config entries we created earlier<\/p>\n<ol>\n<li><strong>Application (client) ID<\/strong> GUID should be placed in the value property for ida:ClientId.<\/li>\n<li><strong>Directory (tenant) ID<\/strong> GUID should be placed in the value property for ida:TenantId.<\/li>\n<\/ol>\n<p>Finally, let\u2019s get your domain name. Navigate to the <strong>Overview page of your AAD<\/strong>. One way is to click on the Azure Active Directory menu item in the far left. Near the top will show the name of your domain. It may be &lt;something&gt;.onmicrosoft.com or it may be your organization\u2019s domain name, like microsoft.com or something similar. Once you have that, place that in the web.config for the ida:Domain setting.<\/p>\n<h2>Step 7: Test<\/h2>\n<p>It\u2019s time to test. Go ahead and launch your site with the Run\/Start Debugging button in Visual Studio. You should then get a login page like:<\/p>\n<p><img decoding=\"async\" width=\"461\" height=\"312\" class=\"wp-image-35046\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2019\/02\/word-image.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2019\/02\/word-image.png 461w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2019\/02\/word-image-300x203.png 300w\" sizes=\"(max-width: 461px) 100vw, 461px\" \/><\/p>\n<p>Go ahead and login. The first time you login you\u2019ll get a prompt like below which you\u2019ll need to <strong>Accept<\/strong>.<\/p>\n<p><img decoding=\"async\" width=\"442\" height=\"414\" class=\"wp-image-35047\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2019\/02\/word-image-1.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2019\/02\/word-image-1.png 442w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2019\/02\/word-image-1-300x281.png 300w\" sizes=\"(max-width: 442px) 100vw, 442px\" \/><\/p>\n<p>After that you\u2019ll get your home page. If you\u2019ve used the same demo app I\u2019ve been using and pasted in the test HTML into About you should navigate to the About page and check your results.<\/p>\n<p>You\u2019ve probably noticed that your group membership checks don\u2019t seem to be working. This is because the information sent to your app actually now has the group GUID, not the group name. Replace the name of the group with it\u2019s GUID in the IsInRole check and you should see it start working again. (The GUID is shown as the Object ID of the group in AAD.)<\/p>\n<h2>Next Steps<\/h2>\n<p>As you deploy your app into other environments, that redirect URL of localhost will no longer be valid. You\u2019ll need to make sure to update the correct value in your web.config as well as add it to the list of allowed redirects in the App Registration. You\u2019ll find that in the Authentication settings above where we turned on the ID tokens in step 5.2 above.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I work with a lot of enterprise customers that have sizable portfolios of Intranet web sites using Web Forms and Windows Integrated Authentication that they would like to move to Azure PaaS; however, we\u2019ve found that a lot of documentation on these topics doesn\u2019t extend back to Web Forms and instead targets .NET Core and MVC.<\/p>\n","protected":false},"author":582,"featured_media":37840,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[25,55],"tags":[67,69],"class_list":["post-35045","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure","category-web","tag-asp-net","tag-azure-ad"],"acf":[],"blog_post_summary":"<p>I work with a lot of enterprise customers that have sizable portfolios of Intranet web sites using Web Forms and Windows Integrated Authentication that they would like to move to Azure PaaS; however, we\u2019ve found that a lot of documentation on these topics doesn\u2019t extend back to Web Forms and instead targets .NET Core and MVC.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/35045","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/users\/582"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/comments?post=35045"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/35045\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/media\/37840"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/media?parent=35045"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/categories?post=35045"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/tags?post=35045"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}