The LoginByToken sample creates a custom policy assertion that is derived from the .NET class SecurityPolicyAssertion. The assertion class gives the .NET framework access to the SAML token and the X509 certificate.
The sample performs the following operations to set up the security policy and message handling.
The following example shows the LoginByTokenSample class method GetSecurityPolicyAssertionForHokToken. The method returns a CustomSecurityAssertionHok instance which overrides the .NET class SecurityPolicyAssertion. The security assertion contains the SAML token and the X509 certificate token. This code is taken from the LoginByToken project file samples/LoginByToken/CustomSecurityAssertionHok.cs.
private SecurityPolicyAssertion GetSecurityPolicyAssertionForHokToken(XmlElement xmlToken) { //When this property is set to true, client requests that use the POST method //expect to receive a 100-Continue response from the server to indicate that //the client should send the data to be posted. This mechanism allows clients //to avoid sending large amounts of data over the network when the server, //based on the request headers, intends to reject the request ServicePointManager.Expect100Continue = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; X509Certificate2 certificateToBeAdded = new X509Certificate2(); string certificateFile = ConfigurationManager.AppSettings["PfxCertificateFile"]; string password = ConfigurationManager.AppSettings["PfxCertificateFilePassword"]; certificateToBeAdded.Import(certificateFile, password ?? string.Empty, X509KeyStorageFlags.MachineKeySet); var customSecurityAssertion = new CustomSecurityAssertionHok(); customSecurityAssertion.BinaryToken = xmlToken; customSecurityAssertion.TokenType = strSamlV2TokenType; customSecurityAssertion.SecurityToken = new X509SecurityToken(certificateToBeAdded); return customSecurityAssertion; }
A vCenter Single Sign-On client provides a custom output filter for the custom security assertion. The custom filter provides three methods:
The following code example demonstrates how to create a custom output filter.
internal class CustomSecurityClientOutputFilterHok : SendSecurityFilter { IssuedToken issuedToken = null; string samlAssertionId = null; MessageSignature messageSignature = null; /// Create a custom SOAP request filter. /// (Save the token and certificate.) public CustomSecurityClientOutputFilterHok(CustomSecurityAssertionHok parentAssertion) : base(parentAssertion.ServiceActor, true) { issuedToken = new IssuedToken(parentAssertion.BinaryToken, parentAssertion.TokenType); samlAssertionId = parentAssertion.BinaryToken.Attributes.GetNamedItem("ID").Value; messageSignature = new MessageSignature(parentAssertion.SecurityToken); } /// Secure the SOAP message before its sent to the server. public override void SecureMessage(SoapEnvelope envelope, Security security) { //create KeyInfo XML element messageSignature.KeyInfo = new KeyInfo(); messageSignature.KeyInfo.LoadXml(CreateKeyInfoSignatureElement()); security.Tokens.Add(issuedToken); security.Elements.Add(messageSignature); } /// Helper method to create a custom key info signature element. /// Returns Key info XML element. private XmlElement CreateKeyInfoSignatureElement() { var xmlDocument = new XmlDocument(); xmlDocument.LoadXml(@"<root><SecurityTokenReference xmlns=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"" xmlns:wsse=""http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd"" wsse:TokenType=""http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0""> <KeyIdentifier xmlns=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"" ValueType=""http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID"">" + samlAssertionId + @"</KeyIdentifier></SecurityTokenReference></root>"); return xmlDocument.DocumentElement; } }