Подписание и публикация файла SAML в C # - PullRequest
0 голосов
/ 10 сентября 2018

Я пытаюсь реализовать единый вход с использованием SAML. Идентификатор отправил мне пример запроса, как показано ниже:

<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
AssertionConsumerServiceURL="https://client1.com/MyBank1/ReceiveSAMLResponse"
Destination=" https://tawtheeq.sa/identity-gateway/ReceiveSAMLRequest"
ForceAuthn="false" ID="9eff699e-6e2c-487c-940f-1f67c226f423" IsPassive="false"
IssueInstant="2018-02-05T07:49:14.992Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Version="2.0">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> https://client1.com/</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:SignedInfo>
        ...
    </ds:SignedInfo>
    <ds:SignatureValue>
        tKSzhWGSv...FPbhwPQ==
    </ds:SignatureValue>
    <ds:KeyInfo>
        <ds:X509Data>
            <ds:X509Certificate>MIIDZz...tlak4=</ds:X509Certificate>
        </ds:X509Data>
    </ds:KeyInfo>
</ds:Signature>
<samlp:NameIDPolicy AllowCreate="true"
    Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" />
<samlp:RequestedAuthnContext Comparison="exact">
    <saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
    </saml:AuthnContextClassRef>
</samlp:RequestedAuthnContext>

Они также предоставили мне свой файл сертификата .cer для проверки подписи в ответе, файл .cer, который я могу использовать в качестве нашего файла .cer, пароля хранилища ключей и псевдонима и файла keystore.jks.

Я создал образец веб-проекта для тестирования. Пустую страницу, нажав на эту кнопку одной кнопкой. Я создаю объект X509Certificate2, используя наш файл (SP) .cer и создаю testXML, затем подписываю и, наконец, отправляю запрос на URL. Ниже приведен код, который я использую.

public partial class _default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }


    protected void SendRequest_Click(object sender, EventArgs e)
    {

        string RequestURL = "https://tawtheeq.sa:8443/identity-gateway-test/ReceiveSAMLRequest";
        var certificate = new X509Certificate2(@"my-bank1-public.cer");

        XmlDocument xml = CreateSomeXml("textXML");
        var guid = Guid.NewGuid();
        var signedXml = SignDoc(xml, certificate, guid.ToString(), guid.ToString());

        PostXMLData(RequestURL, signedXml.ToString());

    }   
    public void PostXMLData(string destinationUrl, string requestXml)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(destinationUrl);
        byte[] bytes;
        bytes = System.Text.Encoding.ASCII.GetBytes(requestXml);
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = bytes.Length;
        request.Method = "POST";
        Stream requestStream = request.GetRequestStream();
        requestStream.Write(bytes, 0, bytes.Length);
        requestStream.Close();
        HttpWebResponse response;
        response = (HttpWebResponse)request.GetResponse();

        //Response.RedirectPermanent(response.ResponseUri.);
        //if (response.StatusCode == HttpStatusCode.OK)
        //{
        //    Stream responseStream = response.GetResponseStream();
        //    string responseStr = new StreamReader(responseStream).ReadToEnd();
        //    return responseStr;
        //}
    }
    public static XmlElement SignDoc(XmlDocument doc, X509Certificate2 cert2, string referenceId, string referenceValue)
    {

        SamlSignedXml sig = new SamlSignedXml(doc, referenceId);
        // Add the key to the SignedXml xmlDocument. 
        sig.SigningKey = cert2.PrivateKey;

        // Create a reference to be signed. 
        Reference reference = new Reference();

        reference.Uri = String.Empty;
        reference.Uri = "#" + referenceValue;

        // Add an enveloped transformation to the reference. 
        XmlDsigEnvelopedSignatureTransform env = new
            XmlDsigEnvelopedSignatureTransform();
        XmlDsigC14NTransform env2 = new XmlDsigC14NTransform();

        reference.AddTransform(env);
        reference.AddTransform(env2);

        // Add the reference to the SignedXml object. 
        sig.AddReference(reference);

        // Add an RSAKeyValue KeyInfo
        // (optional; helps recipient find key to validate). 
        KeyInfo keyInfo = new KeyInfo();
        KeyInfoX509Data keyData = new KeyInfoX509Data(cert2);

        keyInfo.AddClause(keyData);

        sig.KeyInfo = keyInfo;

        // Compute the signature. 
        sig.ComputeSignature();

        // Get the XML representation of the signature
        // and save it to an XmlElement object. 
        XmlElement xmlDigitalSignature = sig.GetXml();

        return xmlDigitalSignature;
    }

    public static XmlDocument CreateSomeXml(string FileName)
    {
        // Create a new XmlDocument object.
        XmlDocument document = new XmlDocument();

        // Create a new XmlNode object.
        XmlNode node = document.CreateNode(XmlNodeType.Element, "", "MyElement", "samples");

        // Add some text to the node.
        node.InnerText = "Example text to be signed.";

        // Append the node to the document.
        document.AppendChild(node);

        // Save the XML document to the file name specified.
        XmlTextWriter xmltw = new XmlTextWriter(FileName, new UTF8Encoding(false));
        document.WriteTo(xmltw);
        xmltw.Close();
        return document;
    }
}

public class SamlSignedXml : SignedXml
{
    private string _referenceAttributeId = "";
    public SamlSignedXml(XmlDocument document,
                 string referenceAttributeId) : base(document)
    {
        _referenceAttributeId = referenceAttributeId;
    }
    public override XmlElement GetIdElement(
        XmlDocument document, string idValue)
    {
        return (XmlElement)
            document.SelectSingleNode(
                string.Format("//*[@{0}='{1}']",
                _referenceAttributeId, idValue));
    }
}

Подписанный XML из кода не является правильным, и он не работает, когда я пытаюсь опубликовать файл:

<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n- 
20010315" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="">
 <Transforms>
  <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped- 
signature" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>zSI5ZAMmQ+8u7R2rP7aAPT6nNQw=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue xmlns="http://www.w3.org/2000/09/xmldsig#">EncryptedKey</SignatureValue>

Примечание: Я удалил зашифрованный ключ из подписанного xml.

Мои вопросы:

  1. Правильно, почему для этой интеграции я впервые работаю с SAML SSO.
  2. Какая польза от Keystore в этой ситуации.
  3. Буду признателен, если вы поделитесь со мной какой-нибудь полезной статьей на эту тему.

Спасибо

...