Koen about .Net

September 2, 2010

Configuration of WIF

Filed under: Development, dotnetmag — Tags: , — koenwillemse @ 16:15

The current project I’m working on is a Identity Management Solution for a client. We’re working with WIF (as you might have noticed in my previous posts) and SPML v2. I’ve been beating my head against a wall for the last few days because we had all kind of problems to get the Identity Delegation scenario working. Eventually it was a small thing which caused all kinds of problems, but I’ll elaborate on that in a different post.

One thing that I found frustrating is the lack of documentation for WIF and especially that it’s difficult that way to configure the identity related stuff correctly. We figured out now what all the configuration items in the microsoft.IdentityModel section mean, so I’m sharing it here so that other people starting with WIF don’t have the same giant learning curve we had ;-).

For a consuming application, the following is a common configuration when using an active STS (note that we use the .NET 3.5 targeted assemblies):

<microsoft.identityModel>
    <service saveBootstrapTokens="true">
        <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            <trustedIssuers>
                <add thumbprint="9dbc8c485022a10788832ab285a6281fe18a22de" name="CN=sts" />
            </trustedIssuers>
        </issuerNameRegistry>
        <audienceUris>
            <add value="http://frontend" />
        </audienceUris>
        <securityTokenHandlers></securityTokenHandlers>
        <federatedAuthentication>
            <wsFederation passiveRedirectEnabled="false" issuer="https://sts/SecurityTokenService.svc" realm="http://frontend" requireHttps="false" />
            <cookieHandler requireSsl="false" />
        </federatedAuthentication>
        <serviceCertificate>
            <certificateReference x509FindType="FindByThumbprint" findValue="4fa9361d1ddda6e8847313a56ab96412dd40f13b" storeLocation="LocalMachine" storeName="My"/>
        </serviceCertificate>
     </service>
</microsoft.identityModel>

Now what does all this mean and what is it for?

  1. saveBootstrapTokens=”true”
    This means that when WIF makes an ClaimsIdentity from a received SecurityToken, that the property BootstrapToken of the ClaimsIdentity will be the actual token received. I wish I had found about this earlier.
  2. issuerNameRegistry
    This section indicates which sts you trust. Here you add the certificate(s) which are used to sign the tokens you receive from the STS
  3. audienceUris
    This section is used to check whether the received information from the STS is applicable to you as the calling application. It should match the AppliesTo property which you set when you issue a RequestForSecurityToken to your STS.
  4. securityTokenHandlers
    In this section you can remove the default handlers and add your own token handlers. Note 1: Don’t clear the collection, because most of them are necessary. If you want to use a custom, then only remove the default of the type you want to add. Note 2: Be very careful with what you do here. One wrong decision here has cost us a lot of hours of bug hunting.
  5. federatedAuthentication
    This section contains information to determine if you are using an active or passive scenario. When you have a passive scenario (when the browser handles the redirects etcetera for you) then you set passiveRedirectEnabled=”true”. You have to make sure then that the correct issuer and realm and other related attributes are set.
    The cookieHandler requireSsl attribute indicates whether the written session cookie requires SSL. When you are working on a non-ssl connection and you forget to set this to false, your cookies won’t be preserved over postbacks.
  6. serviceCertificate
    This section was the least clear to me when starting out. It is for defining which certificate should be used to decrypt the incoming SecurityToken.

When you setup these values correctly, you should get up and running pretty quickly. This post is just for making clear what each section of the configuration is for. To get an overview of all steps to do for getting up and running using an active STS, please read my previous post about making a web application use an active STS.

I hope this helps some of you to save some time when configuring WIF.

Advertisements

August 2, 2010

Making a web application use an active STS

Filed under: Development, dotnetmag — Tags: , , , — koenwillemse @ 19:46

At my current assignment we’re working on a solution which among others consists of a custom Security Token Service which is used for the authentication of users in a web portal. In our case we’ve created an active STS by using Windows Identity Foundation and WCF. We’re now working a demo web application which uses the STS (and some other functionality we’re building) to show the team which creates the portal how they should consume the STS.

Since there is almost NO decent documentation about WIF, I started googling. The problem which I ran into was that the information I found was almost all about scenario’s with a passive STS. I found a bit information about consuming an active STS but all not complete, so I’ll put all the steps I had to take right here, so it can help some others.

First of all, I eventually found this blog post, which made it almost work for me. There was just some information missing which caused me to search for another 1 – 2 hours.

These are the steps to take when you want to consume an active STS from a web application:

  1. Add a reference to the Microsoft.IdentityModel assembly (WIF).
  2. Add the definition of the microsoft.IdentityModel config section to your config like this (check the correct version of the dll of course):
    <section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    
  3. Add the following two HttpModules to your config (when using IIS7, add them to you system.webserver section, otherwise to you system.web section):
    <add name="WSFederationAuthenticationModule" type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    add name="SessionAuthenticationModule" type="Microsoft.IdentityModel.Web.SessionAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  4. The authentication mode should be set to None:
    <authentication mode="None" />
  5. Add the configuration for the microsoft.IdentityModel section, for instance:
    <microsoft.identityModel>
    <service>
    <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
    <trustedIssuers>
    <add thumbprint="{Add the thumbprint of the certificate used by your STS, for instance: 80481e4041bd6758400c62e2c811831b98eed561}" name="{Add the name of the certificate, for instance: CN=devsts}" />
    </trustedIssuers>
    </issuerNameRegistry>
    <audienceUris>
    <add value="{Add the applies to url of your web application}"/>
    </audienceUris>
    <federatedAuthentication>
    <wsFederation passiveRedirectEnabled="false" issuer="{The address of the STS, for instance: https://devsts/mySts.svc}" realm="{The applies to address of your web application, for instance: http://myrelyingparty.nl}" persistentCookiesOnPassiveRedirects="true" />
    <cookieHandler requireSsl="false" />
    </federatedAuthentication>
    <serviceCertificate>
    <certificateReference x509FindType="FindByThumbprint" findValue="{The certificate used by your STS, for instance: 80481e4041bd6758400c62e2c811831b98eed561}" storeLocation="LocalMachine" storeName="My"/>
    </serviceCertificate>
    </service>
    </microsoft.identityModel> 

    As you can see, you register your information about the certificate being used by your sts and the information about your application, the relying party.
    The line about the cookieHandler was the one that caused me some problems because I didn’t have that. The problem is that my local site was working on http and not https, but the created cookies required https. I didn’t have this line at first, which had the effect that the session cookie was not maintained over postbacks.

  6. After you’ve configured everything, you can use the following code to consume your STS and get an IClaimsIdentity:
    // authenticate with WS-Trust endpoint
    var factory = new WSTrustChannelFactory(
    new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
    new EndpointAddress("<a href="https://devsts/MySts.svc">https://devsts/MySts.svc</a>"));
    factory.Credentials.UserName.UserName = usernameField.Text;
    factory.Credentials.UserName.Password = passwordField.Text;
    var channel = factory.CreateChannel();
    var rst = new RequestSecurityToken
    {
    RequestType = RequestTypes.Issue,
    AppliesTo = new EndpointAddress("http://myrelyingparty.nl/"),
    KeyType = KeyTypes.Bearer
    };
    var genericToken = channel.Issue(rst) as GenericXmlSecurityToken;
    // Now you parse and validate the token which results in a claimsidentity
    var handlers = FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers;
    var token = handlers.ReadToken(new XmlTextReader(new StringReader(genericToken.TokenXml.OuterXml)));
    var identity = handlers.ValidateToken(token).First();
    
    // Create the session token using WIF and write the session token to a cookie
    var sessionToken = new SessionSecurityToken(ClaimsPrincipal.CreateFromIdentity(identity));
    FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
    
    //Perform some redirect
    Response.Redirect("~/secure/default.aspx");
    

In our situation, this was not complete, since we need the SAML token received from the STS furtheron to authenticate to WCF services which we consume. After using reflector and trying something out, it can be easily done by changing just two lines of code. I can be done by the following:

var identity = handlers.ValidateToken(token).First();
Thread.CurrentPrincipal = new ClaimsPrincipal(new IClaimsIdentity [] { new ClaimsIdentity(identity.Claims, token) });

The code itself looks probably a bit strange, since we get a ClaimsIdentity from the ValidateToken and then we create another ClaimsIdentity. I hoped that WIF would have used this way to construct the identity, of at least provide an overload or something to do this. I created the identity like this, since the securitytoken is now availalbe in the BootstrapToken property of the ClaimsIdentity. At first we were thinking that we had to keep the security token in session but that is not necessary when you do it like this. Now we can access it simply with the following lines of code:

var identity = Thread.CurrentPrincipal.Identity as ClaimsIdentity;
var theOriginalSecurityToken = identity.BootstrapToken;

I hope this helps somebody else. It would have saved me a lot of time if I could have found this information somewhere.

Update (17-8-2010)

We’ve been using the code as listed above, but we ran into some problems, because the retrieved token is a GenericXmlSecurityToken which caused problems when supplying it to our backend services.

After some searching I found that it is possible to get the BootstrapToken property filled by WIF, but you need to set a configuration switch (some decent documentation would really be helpfull). All you have to do is change the following in your web application configuration (add the saveBootstrapTokens attribute):

<microsoft.identityModel>
<service saveBootstrapTokens="true>
<issuerNameRegistry ……

The code to creating your principal is then the following:

var identity = handlers.ValidateToken(token).First();
Thread.CurrentPrincipal = new ClaimsPrincipal(new [] { identity });

Now the BootstrapperToken is a SamlSecurityToken which is exactly what we want to be able to authenticate to the backend services. I’ll show in a new post how we have all this tied together.

July 26, 2010

Code quality of WIF

Filed under: Development — Tags: , — koenwillemse @ 16:30

The first thing you notice when you start working with the library is, that there is no xml documentation what so ever. This makes it difficult to work with, without reading a lot of other documentation. Especially when the names of methods do not make it clear what it is doing exactly.

Let me give an example of unclear naming. Take the method Saml11SecurityTokenHandler.ProcessStatement. When just seeing this method name, you’d probably think that it is a method with does something with a statement. Wrong… The first parameter it takes is a list of SamlStatements. Then why is the method not named ProcessStatements? It’s just a small thing, but it’s annoying when you’ve read the book Clean Code and you’re trying to write clean code yourself ;-).

I just had to get it off my chest. The library doesn’t seem to have the quality I’m used to with libraries supplied by Microsoft. I hope that a newer version, at least delivers some good documentation on the methods etc. because it’s not very intuitive to work with. Next to that, let’s be honest, Identity management and authentication is a very important part of an application and it’s absolutely not trivial. The library is very helpful in making it easier to work with a claims based scenario, however, life could be a lot easier with some good documentation ;-).

Create a free website or blog at WordPress.com.

%d bloggers like this: