3

We have a customer trying to use ADFS to SSO on to our web application. We are using the ComponentSpace SAML 2.0 library. The assertion being sent to us looks like:

<Assertion ID="_b8a24809-ab6b-4acd-ad6a-8bcb97bb1889" IssueInstant="2012-05-24T13:30:33.917Z" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
    <Issuer>http://example.com/adfs/services/trust</Issuer>
    <Subject>
        <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">mail@example.com</NameID>
        <SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
            <SubjectConfirmationData NotOnOrAfter="2012-05-24T13:35:33.920Z" Recipient="https://example.com/default.aspx" />
        </SubjectConfirmation>
    </Subject>
    <Conditions NotBefore="2012-05-24T13:30:33.907Z" NotOnOrAfter="2012-05-24T14:30:33.907Z">
        <AudienceRestriction>
            <Audience>https://example.com</Audience>
        </AudienceRestriction>
    </Conditions>
    <AttributeStatement>
        <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress">
            <AttributeValue>mail@example.com</AttributeValue>
        </Attribute>
    </AttributeStatement>
    <AuthnStatement AuthnInstant="2012-05-24T13:30:33.756Z" SessionIndex="_b8a24809-ab6b-4acd-ad6a-8bcb97bb1889">
        <AuthnContext>
                <AuthnContextClassRef>urn:federation:authentication:windows</AuthnContextClassRef>
        </AuthnContext>
    </AuthnStatement>
</Assertion>

The ComponentSpace library is pulling the full SamlResponse from the HTTP post but it reports no Assertions (ie samlResponse.GetAssertions().Count == 0). If I use the ComponentSpace examples it works but I notice all of the elements I build with the ComponentSpace library are prefixed with "saml:" (as I believe it should be).

Should the ComponentSpace library be able to find the Assertion without the saml: prefix or is there a way to configure ADFS to send it correctly?

mavis
  • 3,100
  • 3
  • 24
  • 32
Brad Patton
  • 4,007
  • 4
  • 34
  • 44
  • 1
    Our SAML components (http://www.componentspace.com/saml) ignore the prefix when accessing XML elements etc. Instead, elements are identified by tag name and namespace, which is the correct way to do things in XML. Therefore, we do not reply on the tag name being saml but instead look for the Assertion element under the urn:oasis:names:tc:SAML:2.0:assertion namespace etc. –  Aug 04 '12 at 07:40

3 Answers3

3

A correct SAML response should contain namespace-qualified elements

<saml2p:Response Destination="https://www.google.com/a/squaresquare.biz/acs" IssueInstant="2010-08-04T17:47:20.956Z" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" InResponseTo="djfnhepndikoonjjkeomgplmkjofobhdbdieihpa" Version="2.0" ID="_bd24b4a3514fd93800d2a43cafc98edb">
  <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://my.ssodemo.url.demo.google.com/idp/shibboleth</saml2: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:CanonicalizationMethod>
      <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>
      <ds:Reference URI="#_bd24b4a3514fd93800d2a43cafc98edb">
        <ds:Transforms>
          <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
          <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
            <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="dssaml2saml2p"></ec:InclusiveNamespaces>
          </ds:Transform>
        </ds:Transforms>
        <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
        <ds:DigestValue>m/lUCS3nvfGuSJFKAtIz+ZrfxTU=</ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>PLdYgU9u5KirVrMHNSwYvk6fQ401dMbpuiDXpapKf0eOKC6pN3g7tnTEzvfOaXhkDNXVmGN+lXQ6iUDppWpdO2MbvPVZabOBPU1aAO+CWI53ciC0rYsxpFzQLLMC/7x9Wk7VFFmYEecxAJV+lTWvp8ZKXvwqZbhiTO/23EC0xconGhnwSvKjJWQuLnMMaFWSjDFYyzgsp34cR7aX/eqhhJyA/rr2uFdmgEdagAl+/17ppgHgthgK+PJtX16AALtsoXonv6uybRCX/YiDRvM1VsdwusVq5tXh9V+bTMZcgi/3Eh+Em/OZp0En8pqOngvL19U4LfqG0yJZjoDGkpHuhA==</ds:SignatureValue>
    <ds:KeyInfo>
      <ds:X509Data>
        <ds:X509Certificate>MIIDgjCCAmqgAwIBAgIVAKgIqbzZl7+0p2qjxJFVJs3DE/jxMA0GCSqGSIb3DQEBBQUAMDAxLjAsBgNVBAMTJWh0dHA6Ly93cGgtdWJpcTI3LmhvdC5jb3JwLmdvb2dsZS5jb20wHhcNMTAwNzIxMTcxNTA5WhcNMzAwNzIxMTcxNTA5WjAwMS4wLAYDVQQDEyVodHRwOi8vd3BoLXViaXEyNy5ob3QuY29ycC5nb29nbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAioQsJycRmjPjB2xlH0iSGn14lNbO/jIVgiGIlzZwlPkH1s2TTdwoTKKQBSe2s8AnJ4LliXlne/qWun3peYht0+RhejtB20L+Bw/I+iKQBGpHzgIKdkPGZnemWl9KqWQ/ZYKnY2x6qMEBmhUfYZcawzs26em5a+iaYlrTJNVEZ+QwWvg2/EOJvJNyBkSfXyxia5eAHV38Uy7xn0G5Zc9ge4ckCYj6b8a/UxpPJM61KztzY5coDwReQsDBq+DciGALJPbFk4783TW...etc.etc</ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>
  </ds:Signature>
  <saml2p:Status>
    <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"></saml2p:StatusCode>
  </saml2p:Status>
  <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" IssueInstant="2010-08-04T17:47:20.956Z" ID="_73fe28bcbb68e93df954d8e2f25097b1">
    <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://my.ssodemo.url.demo.google.com/idp/shibboleth</saml2:Issuer>
    <saml2:Subject>
      <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">my_username</saml2:NameID>
      <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
        <saml2:SubjectConfirmationData NotOnOrAfter="2010-08-04T17:52:20.956Z" InResponseTo="djfnhepndikoonjjkeomgplmkjofobhdbdieihpa" Recipient="https://www.google.com/a/squaresquare.biz/acs" Address="172.24.6.38"></saml2:SubjectConfirmationData>
      </saml2:SubjectConfirmation>
    </saml2:Subject>
    <saml2:Conditions NotOnOrAfter="2010-08-04T17:52:20.956Z" NotBefore="2010-08-04T17:47:20.956Z">
      <saml2:AudienceRestriction>
        <saml2:Audience>google.com</saml2:Audience>
      </saml2:AudienceRestriction>
    </saml2:Conditions>
    <saml2:AuthnStatement SessionIndex="f306dd2bff4e9b3ba9218bd70fbaa87404d38a4c79547ac1edc9436a9f222213" AuthnInstant="2010-08-04T17:47:20.953Z">
      <saml2:SubjectLocality Address="172.24.6.38"></saml2:SubjectLocality>
      <saml2:AuthnContext>
        <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
      </saml2:AuthnContext>
    </saml2:AuthnStatement>
  </saml2:Assertion>
</saml2p:Response>
Michael Manoochehri
  • 7,931
  • 6
  • 33
  • 47
3

Namespace qualifications are optional.

Lili
  • 41
  • 2
2

It turns out that the above XML is valid (ADFS adds the namespace to the overall XML but not each element). The problem was that the ComponentSpace library has different methods for getting Signed or Encrypted Assertions and I was just calling the generic GetAssertions. ADFS was generating signed assertions and I needed to call the other function.

Here is the code we ended up with:

IList<EncryptedAssertion> encryptedAssertions = samlResponse.GetEncryptedAssertions();
if (encryptedAssertions.Count > 0 && x509Certificate != null) {

    // Decrypt the assertion
    EncryptedAssertion encryptedAssertion = encryptedAssertions[0];
    XmlElement decryptedElement = encryptedAssertion.DecryptToXml(x509Certificate, null);
    LogMessage("Decrypted assertion: " + decryptedElement.OuterXml);

    // Then verify the signature.
    VerifySignature(x509Certificate, decryptedElement);
    samlAssertion = new SAMLAssertion(decryptedElement);
} else {

    if (samlResponse.GetSignedAssertions().Count > 0) {
        // Get the signed assertion and verify the signature.
        XmlElement signedAssertionElement = samlResponse.GetSignedAssertions()[0];
        LogMessage("Signed assertion: " + signedAssertionElement.OuterXml);

        VerifySignature(x509Certificate, signedAssertionElement);
        samlAssertion = new SAMLAssertion(signedAssertionElement);
    } else {
        // Assertion is not encrypted or signed.
        if (samlResponse.GetAssertions().Count > 0) {
            samlAssertion = samlResponse.GetAssertions()[0];
            LogMessage("Assertion: " + samlAssertion.ToXml().OuterXml);
        } else {
            LogFatalError("No assertions in response");
        }
    }
}
Brad Patton
  • 4,007
  • 4
  • 34
  • 44