Zulfiqar's weblog

Middleware, security & random .Net

Archive for the ‘Geneva’ Category

Geneva Framework & S4U

Posted by zamd on December 23, 2008

Current bits of Geneva framework shipped with a service known as Microsoft "Geneva" Claims To NT Token Service. This service can be used to get a Kerberos token for a user without requiring its password. Windows Server 2003 added a little known extension to Kerberos known as Service-4-User (S4U) and this service internally uses this feature to get a Kerberos token.

 

S4U tokens usually have some special restriction to avoid their misuse. So if service is not running under LocalSystem account then the returned token will only have  impersonation level of Identify, so you can query the returned token for group information etc but you cannot impersonate it to open kernel objects etc.  However if the caller is running as LocalSystem then LSA returns a token with the impersonation level of Impersonate and you can indeed impersonate the user and access kernel object on his behalf.  “Claims To NT Token Service” runs under LocalSystem – so a token acquired using this service can be used to impersonate as well.

This service is actually exposed using a WCF endpoint and as part of Geneva framework you get a proxy client for this service as well. Here is an example of using this proxy client to get a token.

 

    class Program

    {

        static void Main(string[] args)

        {

            string filePath = @"C:\temp\data.txt";

            string data;

            var wi = S4UClient.UpnLogon("abu@bccoss.com");

            using (var wic = wi.Impersonate())

            {

                data = File.ReadAllText(filePath);

            }

        }

    }

 

Posted in Geneva | Leave a Comment »

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

}

Posted in Federation/STS, Geneva | 7 Comments »

Creating a Basic STS using Geneva Framework( aka Zermatt)

Posted by zamd on July 10, 2008

Zermatt (Geneva Framework) is an identity framework built on top of solid WCF foundation. It makes writing custom STSs a breeze as the amount of code you have to write is substantially low compared with, when building the same STS directly on top of WCF. In this post I will show you how to write a basic STS using Zermatt. 

This STS will be used by active clients, which mean, it will expose its token issuance functionality using the WS-Trust protocol. In a later post I will talk about passive clients and WS-Federation protocol. 

So the first step is to drive a class from Zermatt provided SecurityTokenService abstract base class. This class provides most of the plubming required implementing an STS and you have to only provide missing pieces in your derived class. 

class CustomSecurityTokenService : SecurityTokenService{} 

Next you have to override following two methods: 

    protected override Scope GetScope(IClaimsPrincipal principal, RequestSecurityToken request) 

    { 

        Scope scope = base.GetScope(principal, request); 

        scope.EncryptingCredentials = new X509EncryptingCredentials(CertificateUtil.GetCertificate(StoreName.My, StoreLocation.LocalMachine, “CN=localhost”)); 

        return scope; 

    } 

  

    public override ClaimsIdentityCollection  GetOutputSubjects(Scope scope, IClaimsPrincipal principal, RequestSecurityToken request) 

    { 

        ClaimsIdentityCollection collection = new ClaimsIdentityCollection(); 

        collection.Add( new ClaimsIdentity( new Claim( ClaimTypes.Name, “zulfiqar” ) ) ); 

        return collection; 

    } 

In the GetScope method, you get all the information about the requestor and based on that you can select credentials which will be used to encrypt the issued token to the requestor. You can do that in the GetOutputSubjects method as well in which case you don’t need to override GetScope. 

In GetOutputSubjects method you create a collection of claims which will be added to the issued token. In a production STS, this is where you will access the external system to get information about the requestor and will create claims based on that information. In this example, I’m simply returning a single Name claim. That’s it – you are done with STS part. 

Now as an STS is essentially a service, so you need to host it inside a ServiceHost and expose it’s functionality using an Endpoint (Standard WCF stuff). Zermatt also provides a custom service host, known as WSTrustServiceHost – which adds Zermatt specific stuff (configuration etc) to the standard ServiceHost class. 

    SecurityTokenServiceConfiguration config = 

        new SecurityTokenServiceConfiguration(stsAddress, new X509SigningCredentials(stsCert)); 

    stsConfig.SecurityTokenService = typeof(CustomSecurityTokenService); 

    //Create host based on our configuration. 

    stsHost = new WSTrustServiceHost(stsConfig, new Uri(stsAddress)); 

    // Add an endpoint – this can be added using standard config mechansims as well. 

    stsHost.AddServiceEndpoint(typeof(IWSTrustFeb2005SyncContract), 

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

    // open the host now.            

    stsHost.Open(); 

At this point our STS is ready to go. You might have noticed that I’m using the standard WSHttpBinding, which mean my STS will authenticate requestors using windows authenticaiton (default for WSHttpBinding) – and then I can use all that information to inlcude appropraite claims in the returned SAML token. One last important point is that Zermatt is build on top of WCF security model – so I can change the binding to require a certificate or a userName to issue a SAML token.  

 

In the next post I will show how to a write a basic test harnesses for our Security Token Service. 

 

Posted in Geneva | Leave a Comment »

 
Follow

Get every new post delivered to your Inbox.