SAML-Toolkits / java-saml

Java SAML toolkit
MIT License
634 stars 398 forks source link

How to sign a SAML AuthnRequest with X509 Certificate & Private Key #252

Open byxor opened 4 years ago

byxor commented 4 years ago

Hi, I've generated a valid X509 certificate and its associated private key. I'd like to use them to sign an authentication request.

I've configured the Saml2Settings as follows:

return new Saml2Settings() {{
    setStrict(true);

    // ... more settings here, hopefully unrelated to my requirements

    setAuthnRequestsSigned(true);
    setSignatureAlgorithm(RSA_SHA1);
    setSpX509cert(certificate);
    setSpPrivateKey(privateKey);
}};

But when I generate an AuthnRequest with the following code, it doesn't have a signature:

final AuthnRequest authnRequest = new AuthnRequest(settings, false, false, false);
final String samlRequest = authnRequest.getEncodedAuthnRequest();

// decode and inflate

System.out.println(decodedAndInflated.toLowercase().contains("signature")); // false

Here's the full decoded and inflated AuthnRequest:

<?xml version="1.0" encoding="UTF-8"?><samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://localhost/idp" Version="2.0" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" ID="ONELOGIN_3aa047aa-2dd3-4fbe-81f5-2249013734ec" AssertionConsumerServiceURL="https://localhost:5990/product/plugins/servlet/samlconsumer" IssueInstant="2020-02-18T09:48:16Z">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://localhost:5990/product</saml:Issuer>
</samlp:AuthnRequest>

I understand that with HTTP-Redirect bindings, the signature is expected to be provided as a URL parameter. I also understand (correct me if I'm wrong), that with HTTP-POST bindings, the signature should be embedded in the SAML payload.

ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"

It says HTTP-POST bindings are being used, yet there's no signature in the message.

Perhaps the signature is being removed by the DEFLATE encoding? As mentioned in the SAML 2.0 bindings specification:

Any signature on the SAML protocol message, including the <ds:Signature> XML element itself, MUST be removed. Note that if the content of the message includes another signature, such as a signed SAML assertion, this embedded signature is not removed. However, the length of such a message after encoding essentially precludes using this mechanism. Thus SAML protocol messages that contain signed content SHOULD NOT be encoded using this mechanism.

How do I correctly use this library to add a signature to my AuthnRequest?

pitbulk commented 4 years ago

There is no support for embedded signature at AuthnRequest class. The supported binding is the HTTP-Redirect binding and the Signature is generated at the buildRequestSignature of the Auth method.

With the AuthnRequest class you will only get the XML data related to the AuthNRequest, but with no Signature element.

You can sign the AuthNRequest in a similar way than the Metadata XML is signed at the signMetadata method with the Util.addSign method