Zulfiqar's weblog

Architecture, security & random .Net

SAML Token Requestor

Posted by zamd on July 11, 2008


In yesterdays post I have shown you how to create a basic STS using Zermatt. You can use this STS by configuring your clients to use WSFederationHttpBinding however in that case you will never see the token issued by STS. In this post I will show you a direct way to communicate with your STS by using the IssuedSecurityTokenProvider – This is useful for quick testing scenarios or when you need access to the issued token.

TokenProviders are the WCF components which provide the tokens used in message security. There is usually a TokenProvider for each type of security token (Certficate, UserName, Kerberos, IssuedToken etc). IssuedSecurityTokenProvider internally uses a ChannelFactory to communicate with the STS to get the actual token. You can configure this ChannelFactory by adding your custom behaviors to the IssuerChannelBehaviors property of the IssuedSecurityTokenProvider. Here is the code sample.

 

public static void Main()

{

    //This provider internally creates a WCF proxy (ChannelFactory) and uses it to issues RST request.

    IssuedSecurityTokenProvider provider = new IssuedSecurityTokenProvider();

    provider.SecurityTokenSerializer = new WSSecurityTokenSerializer();

 

    provider.TargetAddress = new EndpointAddress(http://localhost/IService”);

    provider.IssuerAddress = new EndpointAddress(http://localhost:9000/STS”);

 

    var be = new WSFederationHttpBinding().CreateBindingElements().Find<SecurityBindingElement>();

    // use the default algo & security versions used by Federation binding.

    provider.SecurityAlgorithmSuite = be.DefaultAlgorithmSuite;

    provider.MessageSecurityVersion = be.MessageSecurityVersion;

 

    // Binding used to communicate with STS.

    provider.IssuerBinding = new WSHttpBinding();

 

    // opent the internal channelfactory.

    provider.Open();

   

    // request token by issuing a WS-Trust RST request.

    var issuedToken = provider.GetToken(TimeSpan.FromMinutes(1));

   

    // print token on the console.

    WSSecurityTokenSerializer serializer = new WSSecurityTokenSerializer(be.MessageSecurityVersion.SecurityVersion);

    var writer = XmlWriter.Create(Console.OpenStandardOutput());

    serializer.WriteToken(writer, issuedToken);

    writer.Flush();

    provider.Close();

}

 

My STS requires Kerberos token to issue a SAML token – so this provider simply uses the kerberos token of the process. If you need to send different token (UserName etc) then you can do that using the IsserChannelBehaviors propery mentioned ealier.

provider.IssuerChannelBehaviors.Add(new IssuerCredBehavior());

And custom behavior looks like this.

public class IssuerCredBehavior : IEndpointBehavior

{

    #region IEndpointBehavior Members

 

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)

    {

        var cc = bindingParameters.Find<ClientCredentials>();

        if (cc == null)

        {

            cc = new ClientCredentials();

            cc.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

            cc.ServiceCertificate.SetDefaultCertificate(“CN=localhost”, StoreLocation.LocalMachine, StoreName.My);

           //Use this client certificate to get a SAML token.

            cc.ClientCertificate.Certificate = CertificateUtil.GetCertificate(StoreName.My, StoreLocation.CurrentUser, “cn=localhost”);

            bindingParameters.Add(cc);

        }

    }

 

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)   {    }

 

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)    {    }

 

    public void Validate(ServiceEndpoint endpoint)    {    }

 

    #endregion

}

Advertisements

7 Responses to “SAML Token Requestor”

  1. Amit said

    Hi,

    I have a WCF service deployed and running on IIS 7. But now I have to modify some setting
    I want to change the MessageProctectionOrder from Default (SignBeforeEncryptAndEncryptSignature ) to SignBeforeEncrypt. How to go abt this.. with minimum changes

    You can mail me on my email id …

    Thanks,
    Amit

  2. zamd said

    You can create a custom ServiceHostFactory and use it in your .svc file rather. Then in CreateServiceHost method change the protection order to your desired settings. something like this.
    public class MyCustomFactory : ServiceHostFactory
    {
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {

    var sh = base.CreateServiceHost(serviceType, baseAddresses);
    foreach (var ep in sh.Description.Endpoints)
    {
    var sbe = ep.Binding.CreateBindingElements().Find<SecurityBindingElement>() as AsymmetricSecurityBindingElement;
    sbe.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
    }
    return sh;
    }
    }

    See this entry for details on how to change protection order.
    http://www.zamd.net/2008/02/10/ChangingMessageProtectionOrderForBuiltinBindings.aspx
    -Zulfiqar

  3. Unknown said

    Hi,

    Came across this post when I tried to find out how to write my own STS client. Extremely helpful. There is one thing though: how can I specify the TokenType with the IssuedSecurityTokenProvider? The rst generated with the code above will leave the token type as empty string. And this might now get through some of the STS implementations which check on that property.

    Thanks a lot!

  4. zamd said

    you can use TokenRequestParameters to customize TokenType, KeyType, KeySizes etc. Something like this:

    provider.TokenRequestParameters.Add(tokenTypeXml);

    and you can create tokenTypeXml using something like:

    var el= new XmlDocument().CreateElement("", "TokenType", "http://docs.oasis-open.org/ws-sx/ws-trust/200512");
    el.InnerText = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1";
    var tokenTypeXml = el.OuterXml;

  5. G. Xue said

    Thanks a lot for your reply! I managed to get it working with a minor change: the namespace for the TokenType element is "http://schemas.xmlsoap.org/ws/2005/02/trust&quot; instead. Maybe it is just that the MSDN WCF sample STS I am running is not fully up to the standard.

    Again many thanks for your help.

    Cheers,

    G. Xue

  6. […] and inside it you would have to tweak IssuedSecurityTokenProvider to force it to use X509 key. See this post on how to work with IssuedSecurityTokenProvider directly. In the next post, I will talk more about […]

  7. […] Comments X509 based proof key… on SAML Token Requestorzamd on Introducing Workflow Security…scott_m on Introducing Workflow Security…zamd on […]

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: