August 2009 Archives

If you open the Geneva Server MMC, right-click the root node in the treeview, and select Service Properties, you'll be presented with this dialog:

ServiceProperties.jpg

What is meant by that Identifier field?  What does it do and what is it for?  I wondered that too, and Hervey Wilson of the Geneva team told me that it has these two purposes:
  • When Geneva Server is in the identity provider role, this identifier is the Issuer URI of the STS which get included in tokens issued by it.
  • When Geneva Server is in the federation provider role, this ID is the audience URI that the STS will accept tokens with.

Let me save you a week, and explain how you can pull Geneva Server's active STS apart from its passive STS. What do I mean by this, and why should you care? By passive STS, I mean the Web application that translates WS-Federation and SAML protocol requests to WS-Trust messages. The following diagram, which I lifted from Michele Bustamante's MSDN article, shows how a browser-based client sends SAML- or WS-Federation-compliant messages to Geneva Server's passive STS. From there, this Web app, creates an RST, calls Geneva Server's active STS, and gets the security token back. The login app then translates the RSTR back into a response that conforms to the original protocol used in the request.

The passive STS that Geneva Server comes with can be found in the "WSFederationPassive.Web" subdirectory of the product's installation directory. There's nothing stopping you from customizing it or completely replacing it. If you do take advantage of this extensibility point, you are going to need to debug your Web app. This is fine and easy to do until your backend STS gets more sophisticated and your team gets bigger. With just four developers, a few AD LDS instance for attributes, a SQL Server, and a couple other services you're trying to integrate into the login process, there is no way you can afford to keep setting things up on each Web developer's machine. So, what do you do? You put the active STS, SQL Server, AD LDS, and all your other services in a lab and you point the passive STS being developed on each engineer's machine at that.

This arrangement is not easily achieved. Here are the things you have to do to achieve this. For clarity and brevity, I'm using the following conventions:

Convention

Meaning

P

A certificate used to create a SSL channel and to authenticate the proxy STS on the developer's workstation to the active Geneva Server STS in a lab. This shorthand is used when the public and private portion of the certificate are meant.

Ppr

The private half of P.

Ppu

The public half of P.

H

The DNS name or IP address of the back-end STS server.

H is used as the Common Name (CN) of P. If you don't have name resolution to your lab (I feel your pain!), use the IP address which will avoid the need to update the hosts file on your dev box.

Initial Setup

  1. Create P with a CN of H
  2. Export Ppr

Back-end Geneva Server

If you're using an IP for H, add an IP address of H to the machine. Then, do the following:

  1. Import P into the personal store of the computer account.
  2. Give permission to the account under which Geneva Server runs to read the Ppr.
  3. In IIS, add or edit the HTTPS binding of the default Web site to use Ppu.
  4. Add Ppu to the Trusted Root Certificate Authorities store, thus making it trusted.
  5. In the Geneva Server MMC, add a new proxy using Ppu.
  6. Also in the Geneva Server MMC, right-click the services node to open the Service Properties dialogue box. Enter H in the host name text field, and use H in the identifier as well.

Certificate Configuration on the Developer Workstation

On the developer workstation,

  1. Import P into the personal store of the computer account.
  2. Give read permission for Ppr to the account under which the passive STS Web application runs (e.g., Network Service).
  3. Ensure that P is trusted.

You can ensure that P is trusted in one of two ways:

  1. Add Ppu to the Trusted Root Certificate Authorities store.
  2. Add code such as the following to the Global.asax.cs of the Web app:

public override void Init()
{
    base.Init();

    #if DEBUG
        System.Net.ServicePointManager.ServerCertificateValidationCallback =
            ((sender, certificate, chain, sslPolicyErrors) => true);
    #endif
}

If you try to debug cert-related issues in Firefox by accessing https://H/Trust/Mex (where H again is the active STS's hostname or IP), be sure to read my post from the other night.

Changes to the Passive STS's Web.config

You'll need to update the value of the wsTrustEndpoint attribute to use H and the path "Trust/ProxyCertificateTransport". You should have something like this when you're done:

<microsoft.idenityServer.shared.web>
...
    <securityTokenService samlProtocolEndpoint="net.tpc://127.0.0.1/samlprotocol"
        wsTrustEndPoint="https://H/Trust/ProxyCertificateTransport"
/>
...
</microsoft.idenityServer.shared.web>

Geneva Server App.config Changes on the Developer Workstation

The developer machine needs to have Geneva Server installed on it, though this could be worked around (email me or comment here for details). If you pop open "%ProgramFiles%\Microsoft Geneva Server", the file I'm referring to is called Microsoft.IdentityServer.Servicehost.exe.config.

  1. Add a certificateReference element to the empty serviceIdentityToken element in the microsoft.identityServer.proxy configuration section that is there by default, and use the thumbprint of P in this new certificateReference element.
  2. Replace the empty value in the address attribute of the wsTrustBase element with https://H/Trust/.

You should end up with something like this:

<microsoft.identityServer.proxy>

<host name="" httpPort="80" httpsPort="443" />

<wsTrustBase address="https://H/Trust/"/>
    <serviceIdentityToken>
        <certificateReference
            findValue="<Thumbprint of P> "
            isChainIncluded="False"
            storeName="My"
            storeLocation="LocalMachine"
            x509FindType="FindByThumbprint"/>
        </serviceIdentityToken>
</microsoft.identityServer.proxy>

Conclusion

This was a really hard this to figure out; it took me an entire week with some help from my coworkers. We wouldn't have been able to do it without the help of Hervey Wilson and Colin Brace of the Geneva team. A special thanks to them. It is my hope that by going through this with them it will be easier to do this sort of thing when the product RTMs. If it is, you owe me one ;-)