In my previous post, I showed a basic example of how to use the OWIN Identity provider to configure our application to use a WS-Federation Identity Service. However, that particular way of doing it has one big drawback (well, depending on how you look at it): because you specify the FederationMetadata only, it means that it has to fetch the configuration on the "fly". I didn't measure it (yet), but from my feeling, it significantly increases the initial load time. Additionally, it has one more drawback that is, for our case, a bit more problematic - the server needs to see the STS; which of course makes sense, it has to download the metadata.
However, there are ways of doing it differently...
Our development STS is located behind company firewall, but our development server is hosted on Azure (well, so is the production, but that doesn't matter for the purpose of this post). This meant that OWIN couldn't retrieve the configuration file. My initial fear was that I'll have to abandon OWIN, but that was quickly calmed by the understanding that OWIN is too open for that. More on that in a later post... I did a little bit of Google-ing, and found this post. It deals with a different topic, but it shows the basic concept of manually configuring.
I couldn't find any decent documentation on what to actually do from there on, so I decided to wing it. I know from using WS-Federation before that I need initially, now I needed to figure out how to actually map them from the Federation Metadata document so that I could do it manually. To do that, I looked over the Katana source code, starting at the Handler. Soon, I found the WsFederationConfigurationRetriever class.
Putting the pieces together
In order to tell our OWIN middleware to use our manual configuration, we need to specify the Configuration element inside WsFederationOptions argument to the UseWsFederationAuthentication extension method that we call during app building.
We can create an instance of that as follows:
var wsConfiguration = new WsFederationConfiguration()
Issuer = configurationFabric.Get(Infrastructure.WellKnown.Configurations.Authentication.Issuer),
TokenEndpoint = configurationFabric.Get(Infrastructure.WellKnown.Configurations.Authentication.TokenEndpoint),
wsConfiguration.SigningKeys.Add(new X509SecurityKey(new X509Certificate2(Convert.FromBase64String(
But... how do I figure out what's what?
Well, that's where the source code comes into play. If you look closely enough, you'll see the configuration element is actually "referenced" only three times:
We can match this pretty easily to the Federation Metadata document (XML):
(obviously, the XML file represents an approximate structure, and the data has been removed)
- The EntityID attribute of the XML root corresponds to the Issuer name.
- The X509Certificate element corresponds to a Base64 encoded certificate that is a signing key X509SecurityKey in the configuration element.
- The wsa:Address element corresponds to the TokenEndpoint property which tells the middleware where to actually request the tokens from.
If there's a better way to do this, let me know, I'd love to learn.