{"id":3343,"date":"2015-08-21T00:50:35","date_gmt":"2015-08-21T07:50:35","guid":{"rendered":"http:\/\/www.cloudidentity.com\/blog\/?p=3343"},"modified":"2015-08-21T00:55:11","modified_gmt":"2015-08-21T07:55:11","slug":"openid-connect-web-sign-on-with-adfs-in-windows-server-2016-tp3","status":"publish","type":"post","link":"https:\/\/www.cloudidentity.com\/blog\/2015\/08\/21\/openid-connect-web-sign-on-with-adfs-in-windows-server-2016-tp3\/","title":{"rendered":"OpenId Connect Web Sign On with ADFS in Windows Server 2016 TP3"},"content":{"rendered":"<p>I can\u2019t tell you how excited I am to finally write this post <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-style: none;\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/wlEmoticon-smile1.png\" alt=\"Smile\" \/><\/p>\n<p><a href=\"http:\/\/blogs.technet.com\/b\/server-cloud\/archive\/2015\/08\/19\/what-s-new-in-windows-server-2016-and-system-center-2016-technical-preview-3.aspx\">Yesterday we released the Technical Preview of Windows Server 2016<\/a>. Yes, <a href=\"https:\/\/msdn.microsoft.com\/virtualization\/windowscontainers\">it supports containers natively<\/a>, awesome and groundbreaking,\u00a0 yadda yadda yadda\u2026 but if you follow this blog, I know what you look for every time a new Windows Server comes out: if there are news in ADFS, isn\u2019t it?<br \/>\nBoy, does this release deliver on that. ADFS in Windows Server 2016 TP3 comes with brand new support for OpenId Connect web sign on and for OAuth2 confidential clients \u2013 moreover, it makes it easy to manage all that through its MMC. No more fiddling with Powershell\u2026 unless you are a Powershell wizard, in which case &#8211; carry on, good sir\/madam. <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-style: none;\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/wlEmoticon-smile1.png\" alt=\"Smile\" \/><\/p>\n<p>The ADFS team is going to deliver docs that will cover all the new functionality, but I was too excited to wait \u2013 and I suspect you will be in the same boat, too. So I quickly set up a VM, fiddled with the new ADFS app configuration features and adapted some of our Azure AD sample code to do OpenId Connect based sign in against ADFS. That was all surprisingly fast\u2026 and <strong><em>easy<\/em><\/strong>. The blog below documents that journey. It barely scratches the surface of what\u2019s possible with the new ADFS, but I hope it will show you enough to entice you to try it yourself.<\/p>\n<h2>Setting up ADFS in Windows Server 2016 TP3<\/h2>\n<p>As you guys know, my administrative skills are nil. Every single time I need something administrative done, I hit Lync \u2013 err&#8230; Skype for Business I mean \u2013 and beg Sam or Dean Wells for their help. But this time I could not wait, hence I decided to try my luck and do it myself. Turns out, it wasn\u2019t that hard.<\/p>\n<p>First thing, I downloaded the ISO of WS2013 TP3 from <a href=\"http:\/\/www.microsoft.com\/en-us\/evalcenter\/evaluate-windows-server-technical-preview\">here<\/a>. All it took was a quick &amp; painless sign in and registration with my MSA. The file is 4.8 GB.<\/p>\n<p>That done, I set up a new VM in hyper-V. Note, this is all done on my Surface Pro 3 with Windows 10 Pro. I gave the machine 1GB of RAM (although Windows Server only required 512Mb for running, the VM setup will fail with just that. You can reduce it later) and made sure that I had a decent amount of free space on my disk. Turns out that I didn\u2019t delete my old Windows.old folder \u2013 between that and other housekeeping I ended up with 40Gb free, which were enough to set things up. The VHDX after all the setups is 10.4Gb, hence very reasonable. As network, I assigned to the VM the \u201cSurface Ethernet Adapter Virtual Switch\u201d \u2013 something about the physicality of an ethernet connection makes me feel good. Also remember, when it comes to admin I don\u2019t know what I am doing.<\/p>\n<p>During the VM creation, I specified the downloaded ISO as the setup disk. The booted the VM, and witnessed the usual magic of doing a Windows installation entirely from one SSD \u2013 super fast. During the Windows setup I have chosen the \u201cwith desktop\u201d variant, which for some mysterious reason is not the default. I guess that working on a no-GUI environment satisfies some self-image requirements for admins\u2026 J\/K, of course <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-style: none;\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/wlEmoticon-smile1.png\" alt=\"Smile\" \/><\/p>\n<p>Anyhow, shortly after I was welcomed by the awesome Windows 10 theme. Ta-dahhh.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-width: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image_thumb.png\" alt=\"image\" width=\"1090\" height=\"614\" border=\"0\" \/><\/a><\/p>\n<p>If you set up ADFS in the past, you know what\u2019s next. I had to create an AD, which in my thrift setup meant promoting the VM to be a domain controller. That done, I had to configure the ADFS service.<\/p>\n<p>First thing, I went to the server manager\/local server tab, scrolled down to roles &amp; features, and under \u201ctasks\u201d I selected \u201cAdd Roles and Features\u201d.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image1.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-width: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image_thumb1.png\" alt=\"image\" width=\"1098\" height=\"614\" border=\"0\" \/><\/a><\/p>\n<p>Here, I selected AD DS and ADFS \u2013 as shown below. Note: IIS is not in the default roles, not I am adding it here. Why? Because ADFS in WS2016 does not need it \u2013 it\u2019s all self hosted!<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image2.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-width: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image_thumb2.png\" alt=\"image\" width=\"641\" height=\"456\" border=\"0\" \/><\/a><\/p>\n<p>That done, I hit next until Install was the only option \u2013 and chose it. After some progress bar fun, I landed on the screen below.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image3.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-width: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image_thumb3.png\" alt=\"image\" width=\"639\" height=\"454\" border=\"0\" \/><\/a><\/p>\n<p>Very helpful! I was able to trigger the next step, \u201cpromote this server to a domain controller\u201d, just by clicking on the corresponding link.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image4.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-width: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image_thumb4.png\" alt=\"image\" width=\"620\" height=\"456\" border=\"0\" \/><\/a><\/p>\n<p>I won\u2019t bore you with all the details \u2013 also because I did that this morning and I am writing this blog few hours into the evening, hence I simply don\u2019t remember. The main thing I\u2019ll point out is that I chose the \u201cadd new forest\u201d given that I want a brand new AD, and that I turned off the DNS service because I don\u2019t need it. Ah, and when you are asked to create a new password \u2013 make sure you remember what you choose. It will be required later.<\/p>\n<p>Once you have done all that, the DCpromo will take place\u2026 and will take some time, requiring a long reboot. Not as long as it was in the past, I gather, but not instantaneous nonetheless.<\/p>\n<p>Once you come back in, you\u2019ll be reminded in various places that you didn\u2019t set up ADFS yet \u2013 just click on any of those and you\u2019ll end up in the configuration wizard. Unfortunately I didn\u2019t take too many screenshots of the process, I was too impatient to get to the apps part <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-style: none;\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/wlEmoticon-smile1.png\" alt=\"Smile\" \/> but if I figured this out, I am sure you can figure this out too\u2026 also remember, this is a super early post. The official documentation will follow soon.<\/p>\n<p>Anyhow. Before starting the ADFS configuration in earnest, there\u2019s one task that one has to do: get a certificate that will be used for transport security and signature purposes. Traditional walkthroughs suggest to get a self signed certificate via IIS, but per the above I didn\u2019t have it installed here and did not want to install it just for spitting out an X509. Luckily, I found a super handy way of doing that via Powershell! It\u2019s all thanks to <a href=\"http:\/\/windowsitpro.com\/blog\/creating-self-signed-certificates-powershell\">this article from my good friend Orin<\/a>. I opened a Powershell prompt and entered the following:<\/p>\n<pre class=\"csharpcode\"><strong>New-SelfSignedCertificate<\/strong> -certstorelocation cert:\\localmachine\\my -dnsname WS2016TP3.vibrodomain.net<\/pre>\n<pre class=\"csharpcode\"><\/pre>\n<p>That command created a selfsigned certificate with a subject of my choosing, of the form &lt;machinename&gt;.&lt;domain&gt;, and saved it on the local machine cert store. The command output provided me with the certificate thumbprint.<\/p>\n<p>Next, I exported the certificate to file \u2013 just in case. The next 2 cmdlets did that for me: note that I used the thumbprint for identifying the certificate.<\/p>\n<pre class=\"csharpcode\">$pwd = <strong>ConvertTo-SecureString<\/strong> -String <span class=\"str\">\"whatevah\"<\/span> -Force \u2013AsPlainText<\/pre>\n<pre class=\"csharpcode\"><strong>Export-PfxCertificate<\/strong> -cert cert:\\localMachine\\my\\1C14CE8E9077970CE27D2ED58154ED6B7F768401 -FilePath c:\\WS2016TP3.vibrodomain.net.pfx -Password $pwd<\/pre>\n<p>That done, I went back to the ADFS setup wizard. I am sure you\u2019ll find your way through it, but here there are few hints:<\/p>\n<ul>\n<li>Choose to create\u00a0 a new federation service, as opposed to adding to an existing farm<\/li>\n<li>You\u2019ll see some certificates dropdown, open them and you\u2019ll see the cert you just created \u2013 select it<\/li>\n<li>As the name of the service, pick something consistent with the subject of the certificate you created.<\/li>\n<li>When you are asked to choose what account should run the service, choose the administrator. I don\u2019t know if that\u2019s a good idea in prod \u2013 remember, this is all for dev time. We\u2019ll do more of those things.<\/li>\n<\/ul>\n<p>Once you are done, you should land on the screen below. The warnings below do sound a bit scary, but in the end they did not interfere with setting up the application.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/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-width: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image_thumb5.png\" alt=\"image\" width=\"621\" height=\"456\" border=\"0\" \/><\/a><\/p>\n<p>We are almost done with the setup! I did just another couple of things.<\/p>\n<p>First, I created one test user in the directory \u2013 I don\u2019t like to use the domain admin user directly, given that it has all sorts of odd constraints that are there for excellent reasons in prod but are in the way while developing.<\/p>\n<p>Second, I had to set things up so that I could see ADFS from my host machine, the Surface. To that end:<\/p>\n<ul>\n<li>I found out the IP assigned to my VM, by opening a prompt and typing good ol\u2019 <span style=\"font-family: Consolas;\">ipconfig<\/span>. Say it was <span style=\"font-family: Consolas;\">192.168.1.16<\/span>.<\/li>\n<li>On my Surface, I launched Notepad as administrator and opened the file <span style=\"font-family: Courier New;\">c:\\Windows\\System32\\drivers\\etc\\hosts<\/span>.<\/li>\n<li>In that file, I added the line <span style=\"font-family: Consolas;\">192.168.1.16 WS2016TP3.vibrodomain.net<\/span> \u2013 associating the name I assigned to ADFS with its IP in my setup. I saved and closed the file.<\/li>\n<li>I went back to the VM, opened explorer and navigated to where I saved the exported certificate. I copied it in the clipboard and pasted it on the file system of the Surface. I installed it by double clicking on it and working through the import wizard. I elected to choose where to save the cert, picking the local machine and the trusted authorities store.<\/li>\n<li>Finally, to verify that everything worked \u2013 on the Surface I opened an internet browser and navigated to <a title=\"https:\/\/ws2016tp3.vibrodomain.net\/adfs\/.well-known\/openid-configuration\" href=\"https:\/\/ws2016tp3.vibrodomain.net\/adfs\/.well-known\/openid-configuration\">https:\/\/ws2016tp3.vibrodomain.net\/adfs\/.well-known\/openid-configuration<\/a> \u2013 OMG OMG OMG is that an OpenId Connect discover doc? \u2013 and the prompt \u201cdo you want to open or save openid-configuration.json\u201d confirmed that my host can see the ADFS endpoints on the VM just right.<\/li>\n<\/ul>\n<h2>Setting up a Web App for OpenId Connect sign in ADFS<\/h2>\n<p>NOW we get to the fun part. Go back to the VM and open the ADFS management console.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image6.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\/2015\/08\/image_thumb6.png\" alt=\"image\" width=\"733\" height=\"556\" border=\"0\" \/><\/a><\/p>\n<p>There are lots of interesting news you can find if you drill on each of the folders on the left, but here we\u2019ll concentrate on the most obvious new entry \u2013 the Application Groups folder. That\u2019s the place where ADFS stores application settings. Select it and choose \u201cAdd application group\u201d. You\u2019ll see the wizard below.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/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\/2015\/08\/image_thumb7.png\" alt=\"image\" width=\"731\" height=\"591\" border=\"0\" \/><\/a><\/p>\n<p>The idea is self-explanatory: you are offered a set of application or application topologies templates, covering the gamut of moving parts you encounter in modern authentication. Select some of the entries randomly and you\u2019ll see the wizard steps adapt to the task, growing and shrinking.<\/p>\n<p>Here I am going to the simplest scenario, a web application \u2013 hence I pick up the \u201cserver application or Website\u201d, fill up name and description and click next.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/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-width: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image_thumb8.png\" alt=\"image\" width=\"584\" height=\"472\" border=\"0\" \/><\/a><\/p>\n<p>Looks familiar? : The next steps tells you upfront what clientid is being assigned to your app, and asks you to supply the redirect_uri to use for sending tokens. I plan to use our Azure AD samples or a VS2015 ASP.NET template for actually implement the app, hence I already know what URL to use \u2013 it\u2019s the usual <span style=\"font-family: Courier New;\"><a href=\"https:\/\/localhost:44300\/\">https:\/\/localhost:44300<\/a><\/span>\/ for VS2015 or <span style=\"font-family: Courier New;\"><a href=\"https:\/\/localhost:44320\/\">https:\/\/localhost:44320<\/a><\/span>\/ for the sample. I can add both, just in case! Once done, I click next.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image9.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-width: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image_thumb9.png\" alt=\"image\" width=\"582\" height=\"470\" border=\"0\" \/><\/a><\/p>\n<p>Here I can select which credentials to assign to my app \u2013 big news, given that ADFS didn\u2019t support confidential clients until now. I don\u2019t plan to use any flow requiring creds in this post, but I am adding it anyway for the LOLZ. I chose the \u201cgenerate a shared secret\u201d, corresponding to the string key we use in almost all Azure AD samples. Note that if you don\u2019t write that down NOW, it\u2019s lost forever and you\u2019ll have to reset it\u2026 just like its cloud counterpart.<\/p>\n<p>Also note, super interesting: <strong><u>ADFS can use windows integrated auth as a credential for confidential clients<\/u><\/strong>. That makes total sense\u2026 and it\u2019s awesome. Just think of the daemon scenarios this enables.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image10.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-width: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image_thumb10.png\" alt=\"image\" width=\"583\" height=\"472\" border=\"0\" \/><\/a><\/p>\n<p>Finally, here there\u2019s the summary. It took what \u2013 40 seconds? Pretty awesome.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image11.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-width: 0px;\" title=\"image\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image_thumb11.png\" alt=\"image\" width=\"585\" height=\"472\" border=\"0\" \/><\/a><\/p>\n<p>And we are done \u2013 I mean done done! I can almost hear you. If you have used ADFS in the past, you\u2019re likely to blurt out \u201cwait a minute, what about defining the relying party trust? What about claims mappings\u201d? Have faith, my friends <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-smile\" style=\"border-style: none;\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/wlEmoticon-smile1.png\" alt=\"Smile\" \/> none of that will be necessary.<\/p>\n<h2>Setting up an MVP App to Authenticate via OpenId Connect and ADFS<\/h2>\n<p>I am finally back on my territory. Setting up an app for talking OpenId Connect to Azure AD or ADFS is, surprise surprise, almost exactly the same operation. There are two quick ways of getting to the app we want. One is to use the VS2015 ASP.NET templates to create an app configured to connect to Azure AD, then modify it to talk to ADFS. The other is to clone one of the OpenId Connect samples for Azure AD, and modify it in the same way (the templates are modeled after the samples). Earlier today I did the templates approach, but for this post I\u2019ll show you how to modify our <a href=\"https:\/\/github.com\/AzureADSamples\/WebApp-OpenIDConnect-DotNet\/\">WebApp-OpenIdConnect-DotNet<\/a> sample.<\/p>\n<p>Let\u2019s start by cloning the sample. On Windows I like to use the GitHub desktop client, but of course you can use whatever you prefer.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image12.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\/2015\/08\/image_thumb12.png\" alt=\"image\" width=\"598\" height=\"480\" border=\"0\" \/><\/a><\/p>\n<p>Open the solution in whatever IDE you prefer. The changes are going to be pretty minimal. Here I\u2019ll use VS2013, which just after few weeks of VS2015 already feels retro!<\/p>\n<p>Once the solution is open, compile it \u2013 so that all the missing NuGets are restored. That done, head to the web.config and modify the ida: appSettings entries as follows:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">&lt;<\/span><span class=\"html\">add<\/span> <span class=\"attr\">key<\/span><span class=\"kwrd\">=\"ida:ClientId\"<\/span> <span class=\"attr\">value<\/span><span class=\"kwrd\">=\"8219ab4a-df10-4fbd-b95a-8b53c1d8669e\"<\/span> <span class=\"kwrd\">\/&gt;<\/span>\r\n<span class=\"kwrd\">&lt;<\/span><span class=\"html\">add<\/span> <span class=\"attr\">key<\/span><span class=\"kwrd\">=\"ida:ADFSDiscoveryDoc\"<\/span> <span class=\"attr\">value<\/span><span class=\"kwrd\">=\"https:\/\/ws2016tp3.vibrodomain.net\/adfs\/.well-known\/openid-configuration\"<\/span> <span class=\"kwrd\">\/&gt;<\/span>\r\n<span class=\"rem\">&lt;!--&lt;add key=\"ida:Tenant\" value=\"[Enter tenant name, e.g. contoso.onmicrosoft.com]\" \/&gt;<\/span>\r\n<span class=\"rem\">&lt;add key=\"ida:AADInstance\" value=\"https:\/\/login.microsoftonline.com\/{0}\" \/&gt;--&gt;<\/span>\r\n<span class=\"kwrd\">&lt;<\/span><span class=\"html\">add<\/span> <span class=\"attr\">key<\/span><span class=\"kwrd\">=\"ida:PostLogoutRedirectUri\"<\/span> <span class=\"attr\">value<\/span><span class=\"kwrd\">=\"https:\/\/localhost:44320\/\"<\/span> <span class=\"kwrd\">\/&gt;<\/span><\/pre>\n<p>&nbsp;<\/p>\n<p>In details, the modifications here are:<\/p>\n<ul>\n<li>the ClientId is the value that you got from ADFS while creating the app. You can always retrieve it by going back to the ADFS console, selecting Application Groups, double clicking on the app group entry and then on the app itself in the apps pane. See below:<\/li>\n<\/ul>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image13.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\/2015\/08\/image_thumb13.png\" alt=\"image\" width=\"918\" height=\"704\" border=\"0\" \/><\/a><\/p>\n<ul>\n<li>The ida:ADFSDiscoveryDoc is the address of your ADFS discovery document \u2013 the issuer metadata in OpenId Connect.<\/li>\n<li>The tenant and instance entries aren\u2019t used here hence they can be eliminated<\/li>\n<\/ul>\n<p>That done, we need to tweak the OpenId Connect middleware initialization logic. Head to App_Start\/Startup.Auth.cs, and modify the string inits at the beginning of the file as shown below:<\/p>\n<pre class=\"csharpcode\"><span class=\"kwrd\">private<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">string<\/span> clientId = ConfigurationManager.AppSettings[<span class=\"str\">\"ida:ClientId\"<\/span>];\r\n<strong><span class=\"rem\">\/\/private static string aadInstance = ConfigurationManager.AppSettings[\"ida:AADInstance\"];<\/span>\r\n<span class=\"rem\">\/\/private static string tenant = ConfigurationManager.AppSettings[\"ida:Tenant\"];<\/span>\r\n<span class=\"kwrd\">private<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">string<\/span> metadataAddress = ConfigurationManager.AppSettings[<span class=\"str\">\"ida:ADFSDiscoveryDoc\"<\/span>];<\/strong>\r\n<span class=\"kwrd\">private<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">string<\/span> postLogoutRedirectUri = ConfigurationManager.AppSettings[<span class=\"str\">\"ida:PostLogoutRedirectUri\"<\/span>];\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>No mysteries here, we are just reflecting the changes in the web.config here in code. That done, modify the OpenId Connect middleware options as in the following.<\/p>\n<pre class=\"csharpcode\">app.UseOpenIdConnectAuthentication(\r\n    <span class=\"kwrd\">new<\/span> OpenIdConnectAuthenticationOptions\r\n    {\r\n        ClientId = clientId,\r\n        <strong><span class=\"rem\">\/\/Authority = authority,<\/span>\r\n        MetadataAddress = metadataAddress,\r\n        RedirectUri = postLogoutRedirectUri,<\/strong>\r\n        PostLogoutRedirectUri = postLogoutRedirectUri,\r\n<\/pre>\n<p>What changed:<\/p>\n<ul>\n<li>Instead of using the Authority for communicating data about the trusted issuer, we specify the discovery doc location directly via MetadataAddress<\/li>\n<li>Azure AD does not enforce the rpesence of a redirect_uri in the request, but ADFS does. Hence, we need to add it here<\/li>\n<\/ul>\n<p>That\u2019s it! Hit F5.<\/p>\n<p>Here there\u2019s our good old sample UX.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image14.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\/2015\/08\/image_thumb14.png\" alt=\"image\" width=\"640\" height=\"469\" border=\"0\" \/><\/a><\/p>\n<p>Hit Sign in.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image15.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\/2015\/08\/image_thumb15.png\" alt=\"image\" width=\"640\" height=\"469\" border=\"0\" \/><\/a><\/p>\n<p>Ha! This is exciting! It\u2019s the ADFS default page for forms auth \u2013 very similar to the Azure AD one. Here I am signing in as my test user.<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image16.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\/2015\/08\/image_thumb16.png\" alt=\"image\" width=\"640\" height=\"469\" border=\"0\" \/><\/a><\/p>\n<p>And uneventfully, I am signed in! Note the classic domain\\username identifier on the top right corner \u2013 the logic originally written for Azure AD worked just as well for ADFS.<\/p>\n<p>If you are curious about the content of the default id_token you get from ADFS, you can inspect the incoming ClaimsPrincipal in the index controller (or the immediate window) by adding <span style=\"font-family: Consolas;\">ClaimsPrincipal<\/span> <span style=\"font-family: Consolas;\">cp = ClaimsPrincipal.Current;<\/span> (which comes from the<span style=\"font-family: Consolas;\"> System.Security.Claims<\/span> namespace BTW). Screenshot below:<\/p>\n<p><a href=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/image17.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\/2015\/08\/image_thumb17.png\" alt=\"image\" width=\"640\" height=\"433\" border=\"0\" \/><\/a><\/p>\n<p>And just like that, you have a functioning MVC app authenticating your local AD users via OpenID Connect. Not bad for few mins\u2019 work, you should probably ask for that raise you\u2019ve been thinking about! <img decoding=\"async\" class=\"wlEmoticon wlEmoticon-winkingsmile\" style=\"border-style: none;\" src=\"https:\/\/www.cloudidentity.com\/blog\/wp-content\/uploads\/2015\/08\/wlEmoticon-winkingsmile.png\" alt=\"Winking smile\" \/><\/p>\n<h2>Summary<\/h2>\n<p>Ignore the DCPromo and ADFS setup, which are going to be done by your admins (anyway, that were so straightforward that even I managed to do it in very little time and without help). The new ADFS in the Windows Server 2016 TP3 makes it very easy to provision applications, and its support for modern app topologies is finally comprehensive. The OWIN middleware in Katana \/ ASP.NET, already well proven in Azure AD scenarios, works as is\u00a0 with ADFS \u2013and the delta between the code required in the two cases is risible.<\/p>\n<p>I am loving it.. and that\u2019s only the beginning. Expect upcoming official docs to describe all the other options in depth \u2013 I am sure you will be as delighted and excited as I am right now. Huge kudos to the ADFS team for an awesome prerelease \u2013 I am sure they are looking forward for your feedback.<\/p>\n<p>Go ahead, <a href=\"http:\/\/www.microsoft.com\/en-us\/evalcenter\/evaluate-windows-server-technical-preview\">download Windows Server 2016 TP3<\/a>, set up ADFS and\u2026 happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I can\u2019t tell you how excited I am to finally write this post Yesterday we released the Technical Preview of Windows Server 2016. Yes, it supports containers natively, awesome and groundbreaking,\u00a0 yadda yadda yadda\u2026 but if you follow this blog, I know what you look for every time a new Windows Server comes&#8230;<\/p>\n","protected":false},"author":1,"featured_media":3307,"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-3343","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\/3343","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=3343"}],"version-history":[{"count":2,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/3343\/revisions"}],"predecessor-version":[{"id":3346,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/posts\/3343\/revisions\/3346"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media\/3307"}],"wp:attachment":[{"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/media?parent=3343"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/categories?post=3343"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudidentity.com\/blog\/wp-json\/wp\/v2\/tags?post=3343"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}