Pregunta

The below xml is causing me difficulty. I need to retrieve the following from the XML with c#, can you please help? Also is there a better way of reading/parsing SAML 2.0 response in c#?

  • status code from <samlp:StatusCode value="urn:oasis:names:tc:SAML:2.0:status:**Success**"/>

  • FIRSTNAME Value

  • LASTNAME Value
  • MAIL Value
  • Issuer from <saml:Issuer>**sso.localhost.dev**</saml:Issuer>
  • Audience from <saml:Audience>**Application-Test**</saml:Audience>

XML

    <samlp:Response Destination="http://localhost/SamlAuthenticate" IssueInstant="2014-03-27T14:49:35.395Z" ID="kBWlU3VWF.Ee6DKbkEpFomtlDAT" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">sso.localhost.dev</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#kBWlU3VWF.Ee6DKbkEpFomtlDAT"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>LgH7ZZJWwp5fN02IPteWxh9oAQ8=</ds:DigestValue></ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>gBCZ4upHHdYzrVUcTe4Nf+fElY51UFQOJcf81DFPFNKfFxZfLjnX88NwJ6O7CVU3YNo08EINoEpkvEu+f2oxI3VQVnYnT1EYpLGy1+6qpxsFaPbXaQ8h1/NCwAygir1NDu/sktAzRZ2tg2i5rVn2sevY3Y+47SKnB+hG4ukVHusmNumD0NXyKwKNPflG9XEhrLj3bw5xuftr5CAREX5s1VotANFs1HeJA7OE1Yq2yLhw7GmPsa1+fgYQh5tfFRCmvdnpVoiT+SXwoxlRSbWlf2BWgBOLbC8W4dhTpMFmp70lndk0Pwpnxj6z4jFAHT3z/SdGgm0Ow+TbuutceBIIAQ==</ds:SignatureValue>
</ds:Signature>
<samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status>
<saml:Assertion Version="2.0" IssueInstant="2014-03-27T14:49:35.404Z" ID="w4BForMipBizsG1TA7d9QzhCM0-" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:Issuer>sso.localhost.dev</saml:Issuer>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">JSMITH009</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2014-03-27T14:54:35.404Z" Recipient="http://localhost/SamlAuthenticate"/></saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotOnOrAfter="2014-03-27T14:54:35.404Z" NotBefore="2014-03-27T14:44:35.404Z">
<saml:AudienceRestriction>
<saml:Audience>Application-Test</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2014-03-27T14:49:35.404Z" SessionIndex="w4BForMipBizsG1TA7d9QzhCM0-">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema">
<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="FIRSTNAME">
<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">john</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="MAIL">
<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">john.smith@email.localhost.dev</saml:AttributeValue></saml:Attribute>
<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="LASTNAME"><saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">smith</saml:AttributeValue></saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>
¿Fue útil?

Solución

Got the solution!

public class SAMLProcessor
{

    #region Properties
    public string DecodedSAML { get; set; }
    public string EncodedeSAML { get; set; }
    public string Audience { get; set; }
    public string SubjectNameID { get; set; }
    public string FirstName { get; set; }
    public string Mail { get; set; }
    public string LastName { get; set; }
    public bool AuthenticationStatus { get; set; }
    public string Issuer { get; set; }
    public string Destination { get; set; }
    public string ResponseID { get; set; }
    public bool VerifiedResponse { get; set; }
    public string SignatureValue { get; set; }
    public string SignatureReferenceDigestValue { get; set; }
    public DateTime AutheticationTime { get; set; }
    public string AuthenticationSession { get; set; }
    #endregion


    #region Ctror
    public SAMLProcessor(string rawSamlData)
    {
        EncodedeSAML = rawSamlData;
        // the sample data sent us may be already encoded, 
        // which results in double encoding
        if (rawSamlData.Contains('%'))
        {
            rawSamlData = HttpUtility.UrlDecode(rawSamlData);
        }

        // read the base64 encoded bytes
        string samlAssertion = Decode64Bit(rawSamlData);
        DecodedSAML = samlAssertion;
        SamlParser(DecodedSAML);
    }
    #endregion

    private static string Decode64Bit(string rawSamlData)
    {
        byte[] samlData = Convert.FromBase64String(rawSamlData);

        // read back into a UTF string
        string samlAssertion = Encoding.UTF8.GetString(samlData);
        return samlAssertion;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="samldata"></param>
    /// <returns></returns>
    public string SamlParser(string samlXMLdata)
    {

        //samldata = Decode64Bit("PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4=") + samldata;
        string samldata = samlXMLdata;

        if (!samldata.StartsWith(@"<?xml version="))
        {
            samldata = Decode64Bit("PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4=") + samldata;
        }

        string firstName = string.Empty;
        XmlDocument xDoc = new XmlDocument();
        samldata = samldata.Replace(@"\", "");
        xDoc.LoadXml(samldata);
        //xDoc.Load(new System.IO.TextReader());//Suppose the xml you have provided is stored in this xml file.

        XmlNamespaceManager xMan = new XmlNamespaceManager(xDoc.NameTable);
        xMan.AddNamespace("samlp", "urn:oasis:names:tc:SAML:2.0:protocol");
        xMan.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion");
        xMan.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");


        XmlNode xNode = xDoc.SelectSingleNode("/samlp:Response/samlp:Status/samlp:StatusCode/@Value", xMan);
        if (xNode != null)
        {
            this.AuthenticationStatus = false;
            string statusCode = xNode.Value;
            if (statusCode.EndsWith("status:Success"))
            {
                this.AuthenticationStatus = true;
            }

        }

        xNode = xDoc.SelectSingleNode("/samlp:Response/@Destination", xMan);
        if (xNode != null)
        {
            this.Destination = xNode.Value;
        }
        xNode = xDoc.SelectSingleNode("/samlp:Response/@IssueInstant", xMan);
        if (xNode != null)
        {
            this.AutheticationTime = Convert.ToDateTime(xNode.Value);
        }
        xNode = xDoc.SelectSingleNode("/samlp:Response/@ID", xMan);
        if (xNode != null)
        {
            this.ResponseID = xNode.Value;
        }
        xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Issuer", xMan);
        if (xNode != null)
        {
            this.Issuer = xNode.InnerText;
        }

        xNode = xDoc.SelectSingleNode("/samlp:Response/ds:Signature/ds:SignedInfo/ds:Reference/ds:DigestValue", xMan);
        if (xNode != null)
        {
            this.SignatureReferenceDigestValue = xNode.InnerText;
        }
        xNode = xDoc.SelectSingleNode("/samlp:Response/ds:Signature/ds:SignatureValue", xMan);
        if (xNode != null)
        {
            this.SignatureValue = xNode.InnerText;
        }
        xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Assertion/@ID", xMan);
        if (xNode != null)
        {
            this.AuthenticationSession = xNode.Value;
        }

        xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Assertion/saml:Subject/saml:NameID", xMan);
        if (xNode != null)
        {
            this.SubjectNameID = xNode.InnerText;
        }
        xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Assertion/saml:Conditions/saml:AudienceRestriction/saml:Audience", xMan);
        if (xNode != null)
        {
            this.Audience = xNode.InnerText;
        }

        //reverse order
        //</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>

        //string xQryStr = "//NewPatient[Name='" + name + "']";

        //XmlNode matchedNode = xDoc.SelectSingleNode(xQryStr);
        // samlp:Response  saml:Assertion saml:AttributeStatement saml:Attribute
        xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name = 'FIRSTNAME']/saml:AttributeValue", xMan);
        if (xNode != null)
        {
            this.FirstName = xNode.InnerText;
        }

        // samlp:Response  saml:Assertion saml:AttributeStatement saml:Attribute
        xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name = 'MAIL']/saml:AttributeValue", xMan);
        if (xNode != null)
        {
            this.Mail = xNode.InnerText;
        }

        // samlp:Response  saml:Assertion saml:AttributeStatement saml:Attribute
        xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name = 'LASTNAME']/saml:AttributeValue", xMan);
        if (xNode != null)
        {
            this.LastName = xNode.InnerText;
        }

        return this.FirstName;
    }
}

Otros consejos

If you just want to parse the XML, you can load it into an XElement.

You can also use the Saml2Response class of the Kentor.AuthServices package to parse and validate the response.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top