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:
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 = "https://" + "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:
Custom Security Token Manager:
MyCustomAuthenticator:
MyTokenSerializer:
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:
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="https://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