Подпись как параметр в запросе аутентификации

Я должен получить запрос аутентификации GET с определенным набором параметров:

    "https://domain_name_of_idp_here/idp/profile/SAML2/Redirect/SSO?" + 
"SAMLRequest=" + SAMLRequest + "&SigAlg=" + SigAlg + "&Signature=" + Signature

Итак, меня интересуют параметры:

  • SAMLRequest
  • SigAlg
  • Подпись

Когда я использовал OIOSAML, все эти части запроса формировались автоматически , но гибко управлять ими и получить полный контроль не удалось.

Поэтому я решил написать свой Web SSO на основе SP, используя OpenSAML 2.4.1

Рассмотрим, как создать SAMLRequest. Мой idP требует, чтобы запросы sP-AuthnRequest поступали в следующем формате:

<?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" 
   AssertionConsumerServiceURL=
      "https://ip_of_my_sp_here/oiosaml/saml/SAMLAssertionConsumer" 
   Destination="https://domain_name_of_idp_here/idp/profile/SAML2/Redirect/SSO" 
   ForceAuthn="false" 
   ID="_054240e4-...-e0b5e84d3a35" 
   IsPassive="false" 
   IssueInstant="2012-02-28T06:43:35.704Z" 
   ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" 
   Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
  test_issuer
</saml2:Issuer>

Therefore SAMLRequest I form as follows:

private AuthnRequest buildAuthnRequestObject() {
    DateTime issueInstant = new DateTime();

    IssuerBuilder issuerBuilder = new IssuerBuilder();
    Issuer issuer = issuerBuilder.buildObject(
       "urn:oasis:names:tc:SAML:2.0:assertion", 
       "Issuer", "samlp");
    issuer.setValue(issuerId);

    AuthnRequestBuilder authRequestBuilder = new AuthnRequestBuilder();
    AuthnRequest authRequest = 
        authRequestBuilder.buildObject("urn:oasis:names:tc:SAML:2.0:protocol", 
           "AuthnRequest", "samlp");
    authRequest.setForceAuthn(new Boolean(false));
    authRequest.setIsPassive(new Boolean(false));
    authRequest.setIssueInstant(issueInstant.plusHours(4));
    authRequest.setProtocolBinding(
       "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
    authRequest.setAssertionConsumerServiceURL(consumerUrl);
    authRequest.setDestination(idPDestinationUrlSSO);
    authRequest.setIssuer(issuer);
    authRequest.setID(authReqRandomId);
    authRequest.setVersion(SAMLVersion.VERSION_20); 

    return authRequest;
}

Затем это сообщение сжимается и кодируется в Base64:

private String encodeRequestMessage(RequestAbstractType requestMessage)
        throws MarshallingException, IOException {
    Marshaller marshaller = 
       Configuration.getMarshallerFactory().getMarshaller(requestMessage);
    Element authDOM = marshaller.marshall(requestMessage);

    Deflater deflater = new Deflater(Deflater.DEFLATED, true);
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    DeflaterOutputStream deflaterOutputStream =
            new DeflaterOutputStream(byteArrayOutputStream,
                    deflater);

    StringWriter rspWrt = new StringWriter();
    XMLHelper.writeNode(authDOM, rspWrt);
    deflaterOutputStream.write(rspWrt.toString().getBytes());
    deflaterOutputStream.close();

    String encodedRequestMessage =
            Base64.encodeBytes(byteArrayOutputStream.toByteArray(),
                    Base64.DONT_BREAK_LINES);
    return URLEncoder.encode(encodedRequestMessage, "UTF-8").trim();
}

Таким образом, эта часть - "SAMLRequest =" + SAMLRequest - формируется.

"https://domain_name_of_idp_here/idp/profile/SAML2/Redirect/SSO?" + 
  "SAMLRequest=" + encodedRequestMessage

Что касается СигАлга. Я использую http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23dsa-sha1

Следовательно, эта часть также формируется.

"https://domain_name_of_idp_here/idp/profile/SAML2/Redirect/SSO?" + 
   "SAMLRequest=" + encodedRequestMessage + "&SigAlg=" + SigAlg

Вопрос в формировании этой части:

"&Signature=" + Signature

Я получаю подпись так (но этот метод не дает подпись):

public Signature getSignature() {
    KeyStore keyStore = 
       KeyStore.getInstance(KeyStore.getDefaultType()); 
    FileInputStream fileInputStream = 
       new FileInputStream(new File(jksFileName));
    keyStore.load(fileInputStream, jksPassword);
    fileInputStream.close();        
    KeyStore.PrivateKeyEntry privateKeyEntry =          
       (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, 
          new KeyStore.PasswordProtection(jksPassword));
    PrivateKey privateKey = privateKeyEntry.getPrivateKey();
    X509Certificate certificate = 
       (X509Certificate) privateKeyEntry.getCertificate();
    BasicX509Credential credential = new BasicX509Credential();
    credential.setEntityCertificate(certificate);
    credential.setPrivateKey(privateKey);

    Signature signature = 
    (Signature) org.opensaml.xml.Configuration.getBuilderFactory()               
     .getBuilder(org.opensaml.xml.signature.Signature.DEFAULT_ELEMENT_NAME)
       .buildObject(org.opensaml.xml.signature.Signature.DEFAULT_ELEMENT_NAME);
    signature.setSigningCredential(credential);
    SecurityConfiguration securityConfiguration = 
       Configuration.getGlobalSecurityConfiguration();
    String keyInfoGeneratorProfile = null;
    SecurityHelper.prepareSignatureParams(signature, 
      credential, securityConfiguration, keyInfoGeneratorProfile);

    return signature;
}

В метод buildAuthnRequestObject() добавлено:

private AuthnRequest buildAuthnRequestObject() {
   ...   
   authRequest.setSignature(getSignature()); // <---- to sign the request

   return authRequest;
}

Это сообщение также сжато и закодировано в Base64 и имеет вид:

<?xml version="1.0" encoding="UTF-8"?>
<samlp:AuthnRequest AssertionConsumerServiceURL=
    "https://ip_of_my_sp_here/EsiaChecker_war/resp/"
                    Destination=
    "https://domain_name_of_idp_here/idp/profile/SAML2/Redirect/SSO"
                    ForceAuthn="false" 
                    ID="0" 
                    IsPassive="false" 
                    IssueInstant="2014-09-1T19:07:42.718Z"
                    ProtocolBinding=
         "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"
                    xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
    <samlp:Issuer xmlns:samlp=
         "urn:oasis:names:tc:SAML:2.0:assertion">my_issuer_here
    </samlp: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="#0">
                <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/>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue/>
        <ds:KeyInfo>
            <ds:X509Data>
                <ds:X509Certificate>MIIEXD...0CFtd6whg==
                </ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
    </ds:Signature>
</samlp:AuthnRequest>

Видно, что элемент SignatureValue пуст. Как я могу получить подпись с помощью OpenSaml и добавить ее в качестве параметра запроса GET? Чтобы было так: "&Signature =" + Signature.


person Community    schedule 01.09.2014    source источник


Ответы (1)


Существует компонент под названием HTTPRedirectDeflateEncoder, который поможет в этом, добавляя sigalg, кодируя, дефлируя и перенаправляя пользователя.

У меня есть пример использования в моем блоге, http://blog.samlsecurity.com/2011/01/redirect-with-authnrequest.html

У меня также есть более широкие примеры его использования в моей книге A Guide to OpenSAML

person Stefan Rasmusson    schedule 01.09.2014