Zulfiqar's weblog

Architecture, security & random .Net

Sharing STS object between Active & Passive clients

Posted by zamd on August 16, 2008


Geneva Framework (aka Zermatt) has clean separation between token issuance object model (SecurityTokenService, RequestSecurityTokenRequest etc) and the protocol used to request token. By exploiting this separation, I will show you how to share a single SecurityTokenService object between active (WS-Trust) and passive (WS-Federation) clients. I have already written about Geneva and active clients here so in this post I will focus on passive clients. 

Geneva Framework comes with a sample which implements WS-Federation protocol handler in an ASPX page and for most of the scenarios you will use the same approach. Please refer to “Federation Scenario For Passive Clients” sample for details. The approach I am highlighting here is specific to those scenarios where you want to share the STS object between active & passive clients (Or you don’t want to take a dependency on asp.net pipeline). To achieve this I will create a WCF based protocol handler (using the WCF http support) for WS-Federation protocol. In this handler I will convert the WS-Federation token issuance request into Zermatt token issuance object model (which is very much similar to WS-Trust protocol) and will then forward the request to a shared STS object. 

The service contract for my WS-Federation protocol handler looks like following: 

[ServiceContract] 

public interface IWSFederationService 

{ 

    [OperationContract] 

    [WebGet] 

    Message Issue(string wa, string wtrealm, string wreply, string wctx, string wct); 

} 

I have deliberately named the parameters of this method based on the elements of WS-Federation protocols. This enables WCF QueryStringFormatter to correctly map the values from the HTTP Get “query string” on to these parameters. 

public class ProcessService : IWSFederationService 

{ 

    public Message Issue(string wa, string wtrealm, string wreply, string wctx, string wct) 

    { 

        var col = OperationContext.Current.IncomingMessageProperties[“UriTemplateMatchResults”] as UriTemplateMatch; 

        // Get the shared STS object. 

        var sts = SingletonSTS.Instance; 

         

        var fedSerializer = new WSFederationSerializer(); 

        //create a WS-Federation message for the input data. 

        SignInRequestMessage fedRequest = (SignInRequestMessage)WSFederationMessage.CreateFromUri(col.RequestUri); 

        //convert the federation request into the common WS-Trust based STS model. 

        var rst = fedSerializer.CreateRequest(fedRequest, new WSTrustSerializationContext()); 

        var rstr = sts.Issue(ClaimsPrincipal.Current,rst); 

         

        var rstrStr = fedSerializer.GetResponseAsString(rstr, new WSTrustSerializationContext()); 

        //serialize the token response back into WS-Federation message. 

        var fedResponse = new SignInResponseMessage(new Uri(wreply), rstrStr); 

        fedResponse.Write(Console.Out); 

        // Set appropriate content-type etc. 

        var httpMsg =  Message.CreateMessage(MessageVersion.None, “”,new BinaryBodyWriter(fedResponse)); 

        httpMsg.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Raw)); 

        HttpResponseMessageProperty rmp = new HttpResponseMessageProperty(); 

        rmp.Headers[HttpResponseHeader.ContentType] = “text/html”; 

        httpMsg.Properties.Add(HttpResponseMessageProperty.Name, rmp); 

  

        return httpMsg; 

    } 

} 

With that I can host this service as any other WCF service and I’m ready to issue tokens based on WS-Federation protocol. 

class Program 

{ 

    static CustomSecurityTokenService sts; 

    static void Main(string[] args) 

    { 

        string stsAddress = http://localhost:9000/STS”; 

        SingletonSTS.Init(stsAddress); 

        // For active clients, simply expose this sts over a WS-Trust endpoint. 

        WSTrustServiceHost wsTrustSTSHost = new WSTrustServiceHost(new WSTrustServiceContract(SingletonSTS.Instance), new Uri(stsAddress)); 

        wsTrustSTSHost.AddServiceEndpoint(typeof(IWSTrustFeb2005SyncContract), 

           new WSHttpBinding(), new Uri(stsAddress)); 

        // Make the Active STS ready. 

        wsTrustSTSHost.Open(); 

        Console.WriteLine(“STS is now ready …”); 

        foreach(var ep in wsTrustSTSHost.Description.Endpoints) 

            Console.WriteLine(ep.Address.Uri.AbsoluteUri); 

  

        //make passive STS ready. 

        var wsFedSTSHost = new WebServiceHost(typeof(ProcessService), new Uri(http://localhost/wcf/federation”)); 

        wsFedSTSHost.AddServiceEndpoint(typeof(IWSFederationService), new WebHttpBinding(), “”); 

        wsFedSTSHost.Open(); 

        Console.ReadLine(); 

  

        wsFedSTSHost.Close(); 

        wsTrustSTSHost.Close(); 

    } 

}

Advertisements

2 Responses to “Sharing STS object between Active & Passive clients”

  1. zamd said

    Hi,

    Thanks for the tutorial.

    Is it possible to issue and use Managed Cards with a STS for passive clients?
    I run into the problem that a passive STS needs to be implemented as an .aspx page but that the Managed Card also needs to contain
    a mexhttps address for metadataexchange.

    Is there a way to create a mex endpoint in this scenario using Zermatt?
    Maybe WSFederationMetadataResponseBodyWriter is used for this?

    And why exactly can’t a passive STS be implemented as a .svc endpoint?
    Thanks a lot in advance, I really hope you can help me.

    Best regards

  2. […] http://zamd.net/2008/08/16/sharing-sts-object-between-active-passive-clients/ […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: