Mark and Tom here again, continuing our series on ADFS. In this post, we'll show you how to use some sample-code to configure a web application for Web Single Sign-On (Web SSO) with ADFS.
While Federated Web Single Sign-on (henceforth, SSO) is when two organizations create a federation trust between each other for the purpose of sharing applications while still using their own credentials, most of our customers are setting up ADFS for using Web SSO.
Web SSO is when a claims-aware web application, either on-premise or off-premise, is configured to enable users to login to the application using their existing Active Directory credentials. Great examples of these are ServiceNow for your helpdesk, Dynamics CRM Online for CRM, or an Office 365 SharePoint site for collaboration. In a typical Web SSO transaction, the end-user will navigate directly to the web application and the web application will determine that the user is not authorized and redirect them to their ADFS server. There, they authenticate using integrated Windows authentication or by typing in their credentials. Finally, they get redirected back to the application with a SAML token. The application will then verify the SAML token and the web application will then load.
The key to remember here is that the claims-aware application never communicates with the ADFS server directly. The client's browser handles the responsibility of authenticating against the ADFS server and then the browser receives the SAML token, which it submits to the application. This is the reason that Web SSO is described as a passive request; the browser isn't truly SSO-aware but is still capable of brokering the transaction.
Having a sample claims-aware website that you can install, that also shows the claims that are being sent, can immensely help in understanding Web SSO, how to configure the ADFS components, and how to troubleshoot the claims that are being sent. Once you have this solid foundation, onboarding more Web SSO applications for your users should be much easier.
The requirements are pretty simple. You need:
Let's get to it!
The forest we'll be using is called corp.milt0r.com. The ADFS service URL is https://sts.milt0r.com. Finally, the test application will live on an IIS server at https://adfstest.corp.milt0r.com. In checklist form, you'll need:
We started by grabbing some sample code from MSDN. You can find that code here. Then we were shown some much nicer looking code (Thanks Dave) and used that instead. Since our primary focus in this post is configuring web SSO from an infrastructure standpoint, we aren't going to cover the code itself. To make it even easier, we included a PowerShell script that will set it all up for you. Both are attached at the bottom of this post. Make sure to read the disclaimer…
The setup script is going to do the following:
The script requires Windows Server 2012 or 2012 R2. It will not work on Windows Server 2008 R2. Before running it, you'll need to collect some information. Those items are:
You will need to manually perform the following:
Once you've got that, copy the ZIP file contents up to the IIS server. Unzip the script to a folder, and move the entire deploy folder from the zip file to a location on the system drive. Now, run the script. The parameters are pretty straightforward:
The parameters are as follows:
The script will install everything you need, including the necessary features and roles.
A term you should be very familiar within ADFS is "Relying Party." But what's a relying party? Who's relying on what? The RP can be a couple of things, so simply saying "Relying Party" is vague. Relying Party can refer to:
We've already got our relying party application configured, thanks to the script and files above. Next, we'll need to setup the relying party trust between the application and the ADFS server. To setup the trust, you'll need the following information:
Open up the ADFS Management console and right-click on "Relying Party Trusts" then "Add Relying Party Trust."
Click start in the first screen. On the "Welcome" step is where we'll specify the location for the federation metadata document. Here, you should be able to enter the URL to the metadata document. If the certificate you used in the app isn't trusted by the ADFS server, and you use the Import data about the relying party published online or on a local network option, it will fail. So, if you used our handy script above, you can either 1) trust the self-signed SSL cert on the ADFS server or 2) Use the 2nd option – Import data about the relying party from a file.
If you had to use the 2nd option, it should look something like this:
Notice that we had to use the UNC path to the file, instead of the URL. If the federation metadata isn't published or available, this is also a valid way to configure the relying party trust.
Click next. On the following screen, enter a descriptive name for the application, as well as any notes on why this particular relying party trusts exists (process owner, app owner, related processes, etc).
Click Next. On the Choose Issuance Authorization Rules screen, make sure Permit all users to access the relying party is selected. If you didn't want users to have access, you could deny all by default, then go back and add "Allow" rules after. We'll cover that later.
On the Ready to Add Trust screen, review the settings and click Next. Finally, click Close. Congratulations, you've configured the relying party trust! Now let's test!
Caveat: If your STS is in a domain that is NOT in the same domain as your machine, for example the STS URL in this post is sts.milt0r.com, but the client workstation is in corp.milt0r.com, you'll need to add sts.milt0r.com to your intranet zone in IE to permit Windows Authentication. To do that, in IE go to Internet Options -> Security tab -> Local Intranet -> Click the Sites button -> Advanced. There, add your STS URL (ie, https://sts.milt0r.com) to the list. Click OK.
On your client machine, navigate to your application URL. You should see something like this:
You might end up with a certificate error if you didn't trust the certificate. But, if you see this screen, you've successfully configured web single sign-on between your application and ADFS. The box that says "Issued Identity" is where you'll see any configured claims. We'll cover that more in the next post in this series.
Now, let's take a look at what the authentication flow looks like in Message Analyzer.
First, we ran klist purge on the client machine, and opened an In-Private browser session, just to make sure we didn't use any old cookies. Using Message Analyzer's web proxy and NDIS providers, we're able to view the unencrypted traffic as captured on the client. Navigating to the application URL, the conversation looks like the image below.
1) The browser connects to the web application. Since we're using passive claims, the web app provides a 302 redirect to the browser, pointing it to the ADFS service (Frame 114)
If we dig in to the frame details, we can pull out the entire redirect URL:
2) In the next frames, we can see the browser connect to the ADFS service and receives a 401 challenge.
3) Having purged our Kerberos tickets, we see the full AS/TGS exchange. In 262-275, we see the authentication service requests and replies. In 284 and 288, we see the ticket granting service request for our STS – http/sts.milt0r.com. We've authenticated and received a Kerberos ticket.
4) We present the service ticket to the STS and are authorized. The ADFS service processes our request and, assuming the relying party trust is in place, knows whether or not to issue any claims and what those claims should be. The security token is packaged up and returned in the HTTP reply.
5) Finally, the browser provides the SAML token to the relying party application. Based on the contents of the token, the user may or may not be authorized. In our test app, we get a reply back from the server that contains all of the claims in our token.
We hope this post takes you one step further in the process of getting your ADFS lab built and configured. At this point in the series, you've built an ADFS server, installed a test application on the IIS server, and configured a relying party trust between the test application and the ADFS service. In the next few posts in the series we'll cover federating between two organizations, claim rules, and more. Stay tuned!
A huge thanks to Dave Gregory for providing the much-nicer-than-we-built ClaimsWeb application and some invaluable feedback.
Tom Moser & Mark Morowczynski
@milt0r / @markmorow