SSO with Windows Identity Foundation: Part III - Security Token Service
Welcome back. Today we'll start implementing our security token service or identity provider. Our aim is to verify that there is some form of authentication communication established between the forms authentication application and the STS.
Security Token Service
Think of Forms Authentication again, and imagine if you could take the login form, and place it in another external application. Then imagine you could implement a system, where any unauthenticated request automatically causes a browser redirect to this external login form, and by some magic means the user is redirected back after logging in on that external site. When the user arrives back on the forms app, they would have established identity.
What the external site has in it, is called a Security Token Service in Windows Identity Foundation.
A security token service is basically a class that is concerned with taking in a bunch of identity types, and producing an output identity that our application will understand. It can be fully generic or it can be customized to only work with our application.
A security token service can run inside a WCF, WebAPI or MVC5 application. As long as these applications adhere to a protocol, they can be anything.
STS takes in a bunch of identity types?
Indeed, a single user can have identities in multiple places. They can exist in a corporate Active Directory, but they also might have accounts in Twitter, Facebook and the like, and there might be more user information available in some custom corporate data store. That's just putting the amount of user identity available lightly.
Now it becomes obvious that handling all these identity providers becomes a massive ordeal and your application code base will become extremely polluted with just handling the different types of user identities. Especially if you have application logic that depends on where the user originated from, then you're in for a nightmare.
Would it not be nice to make a separate piece of software that is entirely concerned with all of this, and would allow our business application to be loosely coupled with the concern of figuring out who is who.
And that is exactly what we aim to do - the Security Token Service is concerned with taking all these different identities from all the different sources, and then normalizing them in such a way that your application (the relying party) can consume that identity just like it was coming from the same place every time.
Let's hook our Forms Authentication app to an STS
This part is heavy in configuration and involves a few web.config changes. This is the hardest step in probably the whole thing, and doing it yourself is definitely worth it. Follow my guide carefully here and you won't fail.
Be aware, that these steps can be done with tools, but we'll be doing them manually to learn.
See a Microsoft guide on these steps here. Note that their guide forgets to mention the steps to add the HttpModules, so remember to add those.
Continue by opening our Part 2 Forms Authentication project.
Create another empty MVC5 application with nothing in it, add an authentication controller with the following code and remember to set the RouteConfig to allow route attributes.
Don't worry about this yet, this is debugging code and we'll get back to this in the end.
If you wish, get the above code ready from here.
Run the STS application and make note of what URL it runs in. In my instance it runs at http://localhost:59171/ You will need this in the following steps.
Next, let's change our Forms Authentication app to use our dummy STS by following these steps:
Disable Forms authentication
Add the appropriate HttpModules to intercept requests for authentication requests
Add the system.identityModel and system.identityModel.services sections to the web.config
Verify that the AudienceUri is the same as that of the Forms Auth application.
Verify that the issuer matches the URL of the STS - this is the one I asked you to make note of!
To view the exact changes, check the web.config in this commit and compare it to the one in this commit. View the web.config changes in the diff of this commit to see exactly what changed.
That's it!
Well, that'll do for now. When you start the business application - an immediate redirect will occur to our STS from our Forms Auth app. Let's see what's happening with Fiddler:
So, as you can see, a request is made to our business application, which returns a HTTP 302 Redirect to localhost:59171, and it carries in that redirect a bunch of query parameters.
Let's look at those query parameters:
So what we have here are some mysterious parameters that describe to our STS, what exactly is it that the client wants to do. It tells us we want to sign in (wa), and where are we signing in to (wtrealm). It also tells us where we should redirect after we're done authenticating the user (wreply). If you observed closely, these parameters will match what you put in the web.config of your relying party business app. Swish!
So, now the little bit of code we added into AuthenticationController will actually fire - let's observe what it does:
And let's see what we have in our output:
These keys are keywords specified by the WSFederation standard 13.2. HTTP Protocol Syntax.
So with that, we've established a connection between our STS and the relying party application and are half way done. Next time we'll delve into making sense of the mysterious WSFederationMessage object and actually sending a response to the relying party.
Until next time.