WCF: POC for SAML Token Creation and Consumption

WCF: POC for SAML Token Creation and Consumption

Agenda:

We will understand how we can create a custom SAML token from code and how it can be used to test against a WCF service.

Importance:

This comes handle when we need to work on Interop scenarios and handle the received SAML tokens from Java Clients.

Security Requirement:

Service:

Protocol: Http

Client Credential at soap envelope level: SAML Token

Client:

         Technology: Java Client (For testing, we will use Fiddler)

         SAML Token: Client can get it from some STS or it can be hard coded.

Signing:

Despite we need credential as SOAP envelope level, we cannot use PURE message security.

Because Client will never sign the BODY.

It only sends a Signed SAML token.

Expectation:

WCF to do signature verification for received signed SAML token and parse SAML token to perform authentication/authorization.

Challenges:

The biggest channel is the parse received SAML Token for authentication and authorization.

Incoming Request:

Untitled


Service Security, achieved from custom binding:

static Binding GetBinding()

{

CustomBinding result = new CustomBinding();

TextMessageEncodingBindingElement myEncoding = new TextMessageEncodingBindingElement();

myEncoding.MessageVersion = MessageVersion.Soap12;

//myEncoding.MessageVersion = MessageVersion.Soap12WSAddressing10;

result.Elements.Add(myEncoding);

//SecurityBindingElement mySec = SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);

IssuedSecurityTokenParameters myTokenReq = new IssuedSecurityTokenParameters();

myTokenReq.TokenType = "urn:oasis:names:tc:SAML:2.0:assertion";

myTokenReq.KeyType = System.IdentityModel.Tokens.SecurityKeyType.BearerKey;

SecurityBindingElement mySec= SecurityBindingElement.CreateIssuedTokenOverTransportBindingElement(myTokenReq);

mySec.AllowInsecureTransport = true;

mySec.EnableUnsecuredResponse = true;

mySec.MessageSecurityVersion = MessageSecurityVersion.Default;

//mySec.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;

mySec.SecurityHeaderLayout = SecurityHeaderLayout.Lax;

mySec.LocalServiceSettings.DetectReplays = false;

mySec.IncludeTimestamp = false;

result.Elements.Add(mySec);

HttpTransportBindingElement myTransport = new HttpTransportBindingElement();

result.Elements.Add(myTransport);

return result;

}

Please Note:

I have intentionally left few commented line, to help switch between Addressing mode and client credential as Client Certificate as well.

Service Host:

public static void Test()

{

string baseAddress = "" + "saurabswin7.fareast.corp.microsoft.com" + ":8000/Service";

ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));

host.AddServiceEndpoint(typeof(ITest), GetBinding(), "");

ServiceMetadataBehavior myMeta = new ServiceMetadataBehavior();

myMeta.HttpGetEnabled = true;

host.Description.Behaviors.Add(myMeta);

host.Description.Behaviors.Remove<ServiceCredentials>();

host.Description.Behaviors.Add(new MyCred());

host.Open();

Console.WriteLine("Host opened");

Console.Write("Press ENTER to close the host");

Console.ReadLine();

host.Close();

}

To parse the SAML token, I need to add my custom credentials:

Custom Credentials:

Untitled1


Custom Security Token Manager:

Untitled2


MyCustomAuthenticator:

Untitled3


MyTokenSerializer:

 Untitled4


Useful method to remember:

protected override System.Collections.ObjectModel.ReadOnlyCollection <System.IdentityModel.Policy.IAuthorizationPolicy> ValidateTokenCore(System.IdentityModel.Tokens.SecurityToken token)

protected override SecurityToken ReadTokenCore(XmlReader reader, SecurityTokenResolver tokenResolver)

Creating/Getting SAML Token:

To test the service, we need to create or get a SAML token and then send it to WCF service created with above configuration. I struggle a lot to create a sample STS and get the token, so I would share the relevant code to create SAML token easily.

One Drive Share ( SAML Token Creator and WCF Service Authenticator classes):

https://1drv.ms/f/s!ArgnWb8iHXB6gpRsElvkqkuVjbaAvA

To test the service, we can use Fiddler:

Composer view:

Untitled5


Here I have added extra header to support the

WS Addressing.

Host: saurabswin7.fareast.corp.microsoft.com:8000

Content-Type: application/soap+xml; charset=utf-8; action="tempuri.org/ITest/Echo"

For Body: Get the XML file from the one drive share.

Hope this helps when working on SAML tokens!

Thanks

Saurabh Somani