Share via


ExtractSAMLAssertion

Few people have asked me for the source code of ExtractSAMLAssertion helper method/class, which I have used in my article and blog posts. So here you go...

Please note this is just raw test code and doesn’t have any error checking and other related goodies.

 class Program
{
    static void Main(string[] args)
    {
        var binding = new WSHttpBinding(SecurityMode.Message);
        binding.Security.Message.ClientCredentialType =
            MessageCredentialType.None;
        binding.Security.Message.EstablishSecurityContext =
            false;

        var fac = new WSTrustChannelFactory(binding,
            "https://localhost:9000/STS");
        fac.Credentials.ServiceCertificate.Authentication
            .CertificateValidationMode =
            X509CertificateValidationMode.None;
        fac.Open();

        var rst = new RequestSecurityToken
        {
            AppliesTo =
                new EndpointAddress("https://localhost"),
            RequestType =
                WSTrustFeb2005Constants.RequestTypes.Issue
        };

        var token = fac.CreateChannel().Issue(rst)
            as GenericXmlSecurityToken;
        var rpCert = new X509Certificate2("localhost.pfx",
            "a");
        var xml = ExtractSAMLAssertion(token, rpCert);
    }

    private static string ExtractSAMLAssertion(
        GenericXmlSecurityToken token,
        X509Certificate2 rpCert)
    {
        string txtAssertion = string.Empty;
        var handlerCol =
            SecurityTokenHandlerCollection.
                CreateDefaultSecurityTokenHandlerCollection();
        var han = handlerCol.
            OfType<EncryptedSecurityTokenHandler>()
            .FirstOrDefault();
        if (han != null)
        {
            han.Configuration.ServiceTokenResolver =
                new EncryptedKeyResolver(rpCert);
            var sr = new StringReader(token.TokenXml.OuterXml);
            var rdr2 = XmlReader.Create(sr);
            var rtok = han.ReadToken(rdr2) as SamlSecurityToken;

            var stat = rtok.Assertion.Statements[0];
            var ms = new MemoryStream();
            var memWriter = XmlDictionaryWriter.
                CreateTextWriter(ms);
            stat.WriteXml(memWriter, new SamlSerializer(),
                new WSSecurityTokenSerializer());
            memWriter.Flush();
            ms.Seek(0, SeekOrigin.Begin);

            txtAssertion = new StreamReader(ms).ReadToEnd();
        }
        return txtAssertion;
    }
}

class EncryptedKeyResolver : SecurityTokenResolver
{
    // Relying party certificate - must hold private key.
    X509Certificate2 rpCert;
    public EncryptedKeyResolver(X509Certificate2 rpCert)
    {
        this.rpCert = rpCert;
    }
    protected override bool TryResolveSecurityKeyCore(
        SecurityKeyIdentifierClause keyIdentifierClause,
        out SecurityKey key)
    {
        key = null;
        try
        {
            var ekec = keyIdentifierClause
                as EncryptedKeyIdentifierClause;
            if (ekec != null)
            {
                switch (ekec.EncryptionMethod)
                {
                    case "https://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p":
                        {
                            var encKey = ekec.GetEncryptedKey();

                            var rsa = rpCert.PrivateKey
                                as RSACryptoServiceProvider;
                            var decKey = rsa.Decrypt(encKey,
                                true);

                            key =
                                new InMemorySymmetricSecurityKey(decKey);
                            return true;
                        }
                }
                var data = ekec.GetEncryptedKey();
                var id = ekec.EncryptingKeyIdentifier;
            }
        }
        catch (Exception eexx)
        {
            Console.WriteLine(eexx);
            throw eexx;
        }
        return false;
    }

    protected override bool TryResolveTokenCore(
        SecurityKeyIdentifierClause keyIdentifierClause,
        out SecurityToken token)
    {
        throw new NotImplementedException();
    }

    protected override bool TryResolveTokenCore(
        SecurityKeyIdentifier keyIdentifier,
        out SecurityToken token)
    {
        throw new NotImplementedException();
    }
}

Originally posted by Zulfiqar Ahmed on 13 December 2009 here https://www.zamd.net/2010/03/10/ExtractSAMLAssertion.aspx