iDP connecting to SP SAML / SSO

2019-09-19 15:39发布

问题:

I have been assigned a task where I (the iDP) need to connect to a service provider.

So far I have the code:

public ActionResult SSO(string SAMLRequest)
{
    var model = new ApiSsoModel();

    try
    {
        if (SAMLRequest == null)
            throw new ArgumentNullException("The parameter \"SAMLRequest\" is null.");

        byte[] decoded2 = Convert.FromBase64String(SAMLRequest);
        string decoded3 = string.Empty;

        using (MemoryStream stream2 = new MemoryStream(decoded2))
        {
            using (MemoryStream stream3 = new MemoryStream())
            {
                using (StreamReader reader3 = new StreamReader(stream3))
                {
                    stream2.Position = 0L;
                    new DeflateStream(stream2, CompressionMode.Decompress).CopyTo(stream3);
                    stream3.Position = 0L;
                    decoded3 = reader3.ReadToEnd();
                    reader3.Close();
                }

                stream3.Close();
            }

            stream2.Close();
        }

        string assertion = System.IO.File.ReadAllText(Server.MapPath("~/assertion.xml"));

        CspParameters cspParams = new CspParameters();
        cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";

        RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

        XmlDocument assertionDoc = new XmlDocument();
        assertionDoc.LoadXml(assertion);

        XmlDocument response = new XmlDocument();
        response.LoadXml(decoded3);

        SignedXml signedXml = new SignedXml(assertionDoc);

        Reference reference = new Reference();

        signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
        signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url;

        reference.Uri = "#_79723ebe12aed3704c4d8de6ea16cf90c0d7451da0";

        reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
        reference.AddTransform(new XmlDsigExcC14NTransform());
        reference.DigestMethod = SignedXml.XmlDsigSHA1Url;
        reference.DigestValue = Encoding.ASCII.GetBytes("3jdMJaumbeC3UJ16d8VQJWjKQKU=");

        signedXml.AddReference(reference);

        signedXml.SigningKey = rsaKey;

        HMACSHA256 key = new HMACSHA256();

        signedXml.ComputeSignature(key);

        XmlElement xmlDigitalSignature = signedXml.GetXml();

        assertionDoc.GetElementsByTagName("ds:SignatureValue")[0].InnerText = xmlDigitalSignature.InnerText;

        model.Base64EncodedAssertion = Convert.ToBase64String(Encoding.ASCII.GetBytes(assertionDoc.InnerXml));

        model.Message += "Success";
    }
    catch (Exception ex)
    {
        model.Message = ex.Message;
    }

    return View(model);

}

I am loading up an assertion file which was provided in an SSO 2.0 documentation file

<?xml version="1.0" encoding="UTF-8"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="9f84acebb80533147969eac6a0aead9603c807b5b" Version="2.0" IssueInstant="2015-07-08T09:44:20Z" Destination="https://testdata.redpoints.co.uk/saml/consume" InResponseTo="_e4098d80-0783-0133-f409-7cd1c3f7b75b">
  <saml:Issuer>https://openidp.feide.no</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="#_b9f84acebb80533147969eac6a0aead9603c807b5b">
        <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>3jdMJaumbeC3UJ16d8VQJWjKQKU=</ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>dewQ7U/QjQtaeUHHk/wgzyCLXi0B6mnmMNCUJgj+taxa/c+HsrKVx97iMbMaoFWRd9Ps9SjNr5P40yC2I5j3Dx9pheBAgKX6RRAl0C7CJM36XZAqWwA1CBlDCqx1H3vTeSeotuOovzKVhnpQj9AL38GmFYqHnNS1e5pCfugI72o=</ds:SignatureValue>
    <ds:KeyInfo>
      <ds:X509Data>
        <ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>
  </ds:Signature>
  <samlp:Status>
    <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
  </samlp:Status>
  <saml:Assertion xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ID="_79723ebe12aed3704c4d8de6ea16cf90c0d7451da0" Version="2.0" IssueInstant="2015-07-08T09:44:20Z">
    <saml:Issuer>https://openidp.feide.no</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="#_79723ebe12aed3704c4d8de6ea16cf90c0d7451da0">
          <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>sDFB4zP6PHBacygh64DRtaeowZ8=</ds:DigestValue>
        </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue>GY1M5iO5yht1JLOAOmFBUdZPtxKZeek5jG77w7Ct6A+H1qbUAbX7u8PmniGdOXkllxPWqB+L4Gtd39WbCEoWiQ9QvY/pVz2xe6xzI9gVsnJBP0alalyCZglnxNpQ2x+692OcpVXnbau4LJoFv2+0zktXPhQEI3CfAyixOpASu1w=</ds:SignatureValue>
      <ds:KeyInfo>
        <ds:X509Data>
          <ds:X509Certificate>MIICizCCAfQCCQCY8tKaMc0BMjANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMCTk8xEjAQBgNVBAgTCVRyb25kaGVpbTEQMA4GA1UEChMHVU5JTkVUVDEOMAwGA1UECxMFRmVpZGUxGTAXBgNVBAMTEG9wZW5pZHAuZmVpZGUubm8xKTAnBgkqhkiG9w0BCQEWGmFuZHJlYXMuc29sYmVyZ0B1bmluZXR0Lm5vMB4XDTA4MDUwODA5MjI0OFoXDTM1MDkyMzA5MjI0OFowgYkxCzAJBgNVBAYTAk5PMRIwEAYDVQQIEwlUcm9uZGhlaW0xEDAOBgNVBAoTB1VOSU5FVFQxDjAMBgNVBAsTBUZlaWRlMRkwFwYDVQQDExBvcGVuaWRwLmZlaWRlLm5vMSkwJwYJKoZIhvcNAQkBFhphbmRyZWFzLnNvbGJlcmdAdW5pbmV0dC5ubzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt8jLoqI1VTlxAZ2axiDIThWcAOXdu8KkVUWaN/SooO9O0QQ7KRUjSGKN9JK65AFRDXQkWPAu4HlnO4noYlFSLnYyDxI66LCr71x4lgFJjqLeAvB/GqBqFfIZ3YK/NrhnUqFwZu63nLrZjcUZxNaPjOOSRSDaXpv1kb5k3jOiSGECAwEAATANBgkqhkiG9w0BAQUFAAOBgQBQYj4cAafWaYfjBU2zi1ElwStIaJ5nyp/s/8B8SAPK2T79McMyccP3wSW13LHkmM1jwKe3ACFXBvqGQN0IbcH49hu0FKhYFM/GPDJcIHFBsiyMBXChpye9vBaTNEBCtU3KjjyG0hRT2mAQ9h+bkPmOvlEo/aH0xR68Z9hw4PF13w==</ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </ds:Signature>
    <saml:Subject>
      <saml:NameID SPNameQualifier="https://testdata.redpoints.co.uk/saml/metadata" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">_36355e0a362adec0f5753911aff3b14f9b21d9c2b8</saml:NameID>
      <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
        <saml:SubjectConfirmationData NotOnOrAfter="2017-11-08T09:49:20Z" Recipient="https://testdata.redpoints.co.uk/saml/consume" InResponseTo="_e4098d80-0783-0133-f409-7cd1c3f7b75b" />
      </saml:SubjectConfirmation>
    </saml:Subject>
    <saml:Conditions NotBefore="2015-07-08T09:43:50Z" NotOnOrAfter="2017-11-08T09:49:20Z">
      <saml:AudienceRestriction>
        <saml:Audience>https://testdata.redpoints.co.uk/saml/metadata</saml:Audience>
      </saml:AudienceRestriction>
    </saml:Conditions>
    <saml:AuthnStatement AuthnInstant="2015-07-08T09:15:58Z" SessionNotOnOrAfter="2017-11-08T17:44:20Z" SessionIndex="_066bce0e07565d6a61ae7e94fe95d8bcdd79a3cfd0">
      <saml:AuthnContext>
        <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
      </saml:AuthnContext>
    </saml:AuthnStatement>
    <saml:AttributeStatement>
      <saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
        <saml:AttributeValue xsi:type="xs:string">102112</saml:AttributeValue>
      </saml:Attribute>
    </saml:AttributeStatement>
  </saml:Assertion>
</samlp:Response>

I have tried many different methods to make this work, downloading multiple .net libraries which are meant to help with setting up SSO for the iDP but not had no luck.

回答1:

My reply might not help you but at least it gives you few ideas.

there are 2 flows in SAML:


  1. Sp-Initiated [Service Provider Initiated]: Service provider starts the flow by sending SSO SAML request to the Idp. Idp server process the request and make sure that user is authenticated and authorized to use this service then Idp sends SSO SAML response to Service provider (SP) contains assertions (data about authenticated user).

  2. Idp-Initiated [Identity Provider Initiated]: Idp authenticate and authorize the user and send SSO SAML Request to Service Provider (Only the second part of the Sp-Initiated).

As you are waiting for SAML request. That means your flow is SP-Initiated. First you need to generate your meta data and send it to redpoints. This meta data should at least includes your entityId and SSO end point and X.509 cert for sign/encrypt. You can use onlogin website to generate your metadata

If you already did that. I would recommend you use https://www.componentspace.com/ library. It is fast, efficient and well-maintained. Unfortunately, It is paid but there is a trial period so you can test it.

Have a look on the library documentation on this link

If you use this library, all what you need to do is to add saml.config file as following

<?xml version="1.0"?>
<SAMLConfiguration xmlns="urn:componentspace:SAML:2.0:configuration">
  <IdentityProvider Name="YourEntityId"
                    Description="Description"
                    LocalCertificateFile="Your certificate private key *.pfx"
                    LocalCertificatePassword="Your certificate password"/>

  <PartnerServiceProviders>
    <PartnerServiceProvider Name="https://testdata.redpoints.co.uk/saml/metadata"
                            Description="Red Point Service Provider"
                            <!-- those options should be based on redpoint metadata WantAuthnRequestSigned="true"
                            SignSAMLResponse="false"
                            SignAssertion="true"
                            EncryptAssertion="false"-->
                            AssertionConsumerServiceUrl="https://testdata.redpoints.co.uk/saml/consume"
                            PartnerCertificateFile="Path to redpoint certificate file .cer"/>

  </PartnerServiceProviders>



</SAMLConfiguration>

and add to your action method the following:

 SAMLConfigurationFile.Load();
 string partnerSP = null;
                SSOOptions options = null;
                SAMLIdentityProvider.ReceiveSSO(Request, out partnerSP, out options);
       string userName = "robert@test.com";
 IDictionary<string, string> attributes = new Dictionary<string, string>();
  attributes.Add("NameID", "robert@test.com"); // as an example for possible attribute

    SAMLIdentityProvider.SendSSO(Response, userName, attributes);

I would recommend you also install browser extension to detect SAML requests/response. This is will help you to see the output that you are sending.

I hope my reply gives you a little help.



回答2:

There are a number of SAML stacks around - SAML : SAML connectivity / toolkit .

I would definitely suggest that you don't roll your own. You'll fix this only to come across the next problem.

The problem with most of the stacks is that they are client side. You want server side.

Agree with componentspace suggestion - it can do both sides.

Or this one - currently in beta.

Or have a look at the OpenSAML source - it's Java but the principles are the same.