SAML Token Security Policies

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.
  • Sets the
    ServicePointManager
    properties to specify SSL3 and HTTP 100-Continue response handling. 100-Continue response handling supports more efficient communication between the client and vCenter server. When the client-side .NET framework sends a request to the server, it sends the request header and waits for a 100-Continue response from the server. After it receives that response, it sends the request body to the server.
  • Creates an
    X509Certificate2
    object, specifies the certificate file, and imports the certificate. The certificate file specification indicates a PKCS #12 format file (Public-Key Cryptography Standards) –
    PfxCertificateFile
    . The file contains the client’s private key and public certificate. The
    PfxCertificateFile
    setting is defined in the
    app.config
    file in the
    LoginByToken
    project. The definition specifies the location of the file.
  • Creates a custom security assertion to store the SAML token and the certificate. The token and certificate will be included in the policy data for the
    LoginByToken
    request.
  • Defines a custom output filter that is derived from the .NET class
    SendSecurityFilter
    .

Custom Security Assertion

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.
Setting Up Security Policies
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; }

Custom Output Filter for a vCenter Single Sign-On Client

A vCenter Single Sign-On client provides a custom output filter for the custom security assertion. The custom filter provides three methods:
  • CustomSecurityClientOutputFilterHok class constructor – Creates token and message signature objects for the SOAP message.
  • SecureMessage—An override method for the .NET method
    SendSecurityFilter.SecureMessage
    . The override method adds the SAML token and message signature to the .NET Security element.
  • CreateKeyInfoSignatureElement – Creates an XML document that specifies the SAML token type and ID.
The following code example demonstrates how to create a custom output filter.
Output Filter for the Custom SecurityPolicyAssertion
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; } }