SAML Secured AuthnRequest Fails - saml

I'm not able to make a secured ECP AuthnRequest to my Shibboleth IdP. I've got a small proof of concept SP running which is based heavily on the Spring SAML extension sample app. My SP metadata was generated using the Spring SAML extension sample app's metadata generator. The signing key being used is the apollo one included with the sample app samlKeystore.jks key store, all of which is also in my own small SP app.
In my SP metadata, I have the AuthnRequestsSigned attribute set to true like so :
<md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
If I set AuthnRequestsSigned to false and make the ECP SOAP POST to the IdP, it works just fine. I get the proper SOAP message back from the IdP. But if that value is true, I get a non-descriptive error message:
<env:Fault>
<faultcode>env:Client</faultcode>
<faultstring>An error occurred processing the request.</faultstring>
<detail/>
</env:Fault>
I look in the Shibboleth (IdP) logs and see:
Attempting to extract credential from an X509Data
Found 1 X509Certificates
Found 0 X509CRLs
Single certificate was present, treating as end-entity certificate
Credentials successfully extracted from child {http://www.w3.org/2000/09/xmldsig#}X509Data by provider org.opensaml.xml.security.keyinfo.provider.InlineX509DataProvider
A total of 1 credentials were resolved
This displays twice in the log for my transaction. My assumption is because it's finding the certificate in the request and in my SP metadata. Further down in the log during this same transaction I see this followed by a stack trace:
Attempting to validate signature using key from supplied credential
Creating XMLSignature object
Validating signature with signature algorithm URI: http://www.w3.org/2000/09/xmldsig#rsa-sha1
Validation credential key algorithm 'RSA', key instance class 'sun.security.rsa.RSAPublicKeyImpl'
Signature did not validate against the credential's key
Signature validation using candidate validation credential failed
Signature did not validate against the credential's key
I compared the certificate that is in the ECP POST AuthnRequest to the one in my SP metadata used for "signing" and they are the same. So I'm not sure why I'm getting this error.
My understanding is that the IdP will take the certificate found in the <ds:X509Certificate> tag of the request (which is the public key) and make sure that's the same one defined in the SP metadata. Then use that cert to verify the signature value which is also in the request in the <ds:SignatureValue> element. If it validates then it moves forward with the AuthnRequest. Is this accurate?
What piece am I missing?
Update 1: I've added the logging lines as suggested and here's all it shows for the ECP requests:
signatureMethodURI = http://www.w3.org/2000/09/xmldsig#rsa-sha1
jceSigAlgorithm = SHA1withRSA
jceSigProvider = SunRsaSign
PublicKey = Sun RSA public key, 2048 bits
modulus: <long value here>
public exponent: 65537
Signature verification failed.
One thing of note, if I make a request to my SP via a browser and I'm not signed in, I get redirected to my IdP login page as expected. I check the IdP logs and see that that request was also signed and it validates. I looked at the form data sent to the IdP from the SP and see that AuthnRequest is also signed using the same certificate but the SignatureValue value are different of course. That non-ECP request data XML looks very similar to the ECP request SOAP XML yet the ECP one fails.
UPDATE 2: I'm using spring-security-saml-1.0.0.RELEASE, and Shibboleth IdP v2.4.0. Here's a sample message I'm sending to the IdP:
<?xml version="1.0" encoding="UTF-8"?>
<soap11:Envelope
xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/">
<soap11:Header>
</soap11:Header>
<soap11:Body>
<saml2p:AuthnRequest
xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="http://1XP21VRS.mydomain.com:8080/proofofconceptapp-sso/saml/SSO/alias/conceptSSO" ForceAuthn="false" ID="a3j6fd01d0ciahe25b56i326bhe212" IsPassive="false" IssueInstant="2014-10-24T19:37:43.207Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS" Version="2.0">
<saml2:Issuer
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://1XP21VRS.mydomain.com:8080/proofofconceptapp-sso
</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:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#a3j6fd01d0ciahe25b56i326bhe212">
<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>mMJbjpmWr6OMP9eU70RA9TtfXGY=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>I6rHpgjWgl5l5sjst+VHuSUnjUaOBnPIbUrWwcAfdTDSFY2wxUuNdHpXt/YqBfP9ZKdTWZV1IjbTR666T7sa1bZawgT3UO07FoBVAc5z+AH0nCvIz+UNSqpunPTaEdUhSaGmNHSItvFtvz2fDmvZl18GwXrTz4g6vvxKkdo/FijgvYldfYYuO+obcjof1SJmpOOr1iRNvpyGQMxcaH9e07QfJO9SDcLP2elvPvwbJsGGl/n/3sIG+kIm0MECU3hv/4pLx6+SyHDXjdhdOD2HyxGL1t7iIYG1AaDX4dkIt2wH2WOyzhfO2MyykqChhRcYWFdEdgqaQW/IBLPxsVjN9g==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIDUjCCAjqgAwIBAgIEUOLIQTANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQGEwJGSTEQMA4GA1UE
CBMHVXVzaW1hYTERMA8GA1UEBxMISGVsc2lua2kxGDAWBgNVBAoTD1JNNSBTb2Z0d2FyZSBPeTEM
MAoGA1UECwwDUiZEMQ8wDQYDVQQDEwZhcG9sbG8wHhcNMTMwMTAxMTEyODAxWhcNMjIxMjMwMTEy
ODAxWjBrMQswCQYDVQQGEwJGSTEQMA4GA1UECBMHVXVzaW1hYTERMA8GA1UEBxMISGVsc2lua2kx
GDAWBgNVBAoTD1JNNSBTb2Z0d2FyZSBPeTEMMAoGA1UECwwDUiZEMQ8wDQYDVQQDEwZhcG9sbG8w
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCXqP0wqL2Ai1haeTj0alwsLafhrDtUt00E
5xc7kdD7PISRA270ZmpYMB4W24Uk2QkuwaBp6dI/yRdUvPfOT45YZrqIxMe2451PAQWtEKWF5Z13
F0J4/lB71TtrzyH94RnqSHXFfvRN8EY/rzuEzrpZrHdtNs9LRyLqcRTXMMO4z7QghBuxh3K5gu7K
qxpHx6No83WNZj4B3gvWLRWv05nbXh/F9YMeQClTX1iBNAhLQxWhwXMKB4u1iPQ/KSaal3R26pON
UUmu1qVtU1quQozSTPD8HvsDqGG19v2+/N3uf5dRYtvEPfwXN3wIY+/R93vBA6lnl5nTctZIRsyg
0Gv5AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFQwAAYUjso1VwjDc2kypK/RRcB8bMAUUIG0hLGL
82IvnKouGixGqAcULwQKIvTs6uGmlgbSG6Gn5ROb2mlBztXqQ49zRvi5qWNRttir6eyqwRFGOM6A
8rxj3Jhxi2Vb/MJn7XzeVHHLzA1sV5hwl/2PLnaL2h9WyG9QwBbwtmkMEqUt/dgixKb1Rvby/tBu
RogWgPONNSACiW+Z5o8UdAOqNMZQozD/i1gOjBXoF0F5OksjQN7xoQZLj9xXefxCFQ69FPcFDeEW
bHwSoBy5hLPNALaEUoa5zPDwlixwRjFQTc5XXaRpgIjy/2gsL8+Y5QRhyXnLqgO67BlLYW/GuHE=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
</saml2p:AuthnRequest>
</soap11:Body>
</soap11:Envelope>
I'm pretty much just copying the response from the initial PAOS request to the SP (Spring SAML), removing the header innards, and sending that along to the Shibboleth IdP. The headers that I send are:
Content-Type: text/xml
Authorization: Basic <base64 encoded credential string here>
Update 3: Signed non-ECP AuthnRequests validate just fine. So it's only SOAP ECP AuthnRequests to the IdP where the signature fails. Any ideas?
Update 4: Still can't get this working. Any help would be appreciated.

Related

Apache Knox for SAML2 authentication keeps using NameIDFormat entity instead of what is configured

I am trying to enable SSO capabilities for Apache Zeppelin, using Apache Knox, which is configured to redirect auth requests to a Siteminder IdP.
The issue I am having is related to the NameID format configuration, and the signing configuration.
No matter what I configure in the sp/idp metadata, the NameID format used is
urn:oasis:names:tc:SAML:2.0:nameid-format:entity
And the requests are always being sent with Signed requests set to true.
My SP configuration is as follows:
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://knox.test.com/gateway/knoxsso/api/v1/websso?pac4jCallback=true%26client_name=SAML2Client">
<SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol http://schemas.xmlsoap.org/ws/2003/07/secext">
<NameIDFormat>
urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
</NameIDFormat>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://knox.test.com/gateway/knoxsso/api/v1/websso?pac4jCallback=true%26client_name=SAML2Client"/>
<AssertionConsumerService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" index="1" isDefault="true" Location="https://knox.test.com/gateway/knoxsso/api/v1/websso?pac4jCallback=true%26client_name=SAML2Client"/>
</SPSSODescriptor>
I activated a SAML tracer and attempted the logon user journey. The AuthNRequest being sent to the Siteminder IdP based on this configuration looks like this:
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
AssertionConsumerServiceURL="https://knox.test.com/gateway/knoxsso/api/v1/websso?pac4jCallback=true%26client_name=SAML2Client"
Destination="https://test-siteminder.com/test/saml2sso"
ForceAuthn="false"
ID="_yp52mio0oj4ho2niijmnnaikgbkid9tnc5h5ear"
IsPassive="false"
IssueInstant="2020-02-17T10:19:24.279Z"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
ProviderName="pac4j-saml"
Version="2.0"
>
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
NameQualifier="https://knox.test.com/gateway/knoxsso/api/v1/websso?pac4jCallback=true%26client_name=SAML2Client"
>https://knox.test.com/gateway/knoxsso/api/v1/websso?pac4jCallback=true%26client_name=SAML2Client</saml2:Issuer>
I can see a signature value in the Parameters section of the request, which is why I'm assuming that the AuthNRequest is signed (though my understanding of this is minimal, so that could be a wrong assumption!).
Can anyone help explain why the NameIDFormat is coming through as entity, as opposed to unspecified?
Does Apache knox support SAML1 protocols?
Thanks in advance!
You mentioned NameID format to be urn:oasis:names:tc:SAML:2.0:nameid-format:entity in your post but in the code you pasted it is urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified, just a copy paste error ? Looks like protocolSupportEnumeration is also referencing SAML 1 protocol. Knox uses Pac4J under the hood which does not support SAML 1, this might be the reason.

SP Metadata. WantAssertionsSigned false or true?

I am the SP. I am trying to help the IdP to send me (Unsolicited SSO) SAML assertions appropriately. But What happens is that SAML comes without signature.
In my logs, after callback phase initiates it raises an ERROR message:
ERROR -- omniauth: (saml_degreed) Authentication failure! invalid_ticket: OneLogin::RubySaml::ValidationError, Found an unexpected number of Signature Element. SAML Response rejected
When I copy his SAML message from terminal and 64base decode it, what I see is a jump from element <saml:Issuer> to element <saml:Subject>. There is no <Signature> element.
When I tell him there is no <Signature> element in the message I receive, he sends me (By email) the message he is supposedly sending, with <Signature> element.
Is there something from my side (SP) to be done ? Find below my metadata file. I have already tried to change WantAssertionsSigned to "true" as well as AuthnRequestsSigned, but still failed.
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
cacheDuration="PT604800S"
entityID="https://qa.mypage.com">
<md:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="https://qa.mypage.com/students/auth/saml_test/callback"
index="1" />
</md:SPSSODescriptor>
</md:EntityDescriptor>

Signing auth request in shibboleth SP

I am using Shibboleth SP for SAML authorization.
Recently IdP has changed the configuration and it now requires to sign the AuthRequest.
IdP's metadata has following parameter
<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"
WantAuthnRequestsSigned="true"><md:KeyDescriptor use="signing">
SP's shibboleth2.xml file had following tag
<ApplicationDefaults entityID="...."
REMOTE_USER="eppn persistent-id targeted-id email Email FirstName LastName NameID">
After IdP enforced AuthRequest signing, we changed our shibboleth2.xml file as following
<ApplicationDefaults entityID="..."
REMOTE_USER="eppn persistent-id targeted-id email
Email FirstName LastName NameID"
signing="true" encryption="true">
Basically, I added signing="true" and encryption="true".
After that the new Metadata generated has following attribute in tag
<md:SPSSODescriptor AuthnRequestsSigned="1"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol
urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:1.0:protocol">
Earlier AuthnRequestsSigned="1" attribute was not present.
After this when I try to authenticate, it gives us following error,
<samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder"/>
<samlp:StatusMessage>Unable to verify the signature</samlp:StatusMessage>
</samlp:Status>
Question 1: Do I need to give IdP this new metadata?
Question 2: Any idea why this is happening?
Question 3: Do I need to change anything else in the configuration?
P.S. Before enforcing AuthRequest signing, it was working, so I don't think there is any other issue in configuration.
Here is the sample AuthRequest which goes
<samlp:AuthnRequest
AssertionConsumerServiceURL="https://...SP-host.../Shibboleth.sso/SAML2/POST"
Destination="https://...idp-host.../marrsso/idp/SSO.saml2"
ID="...some-id..." IssueInstant="2019-01-11T14:13:25Z"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://...entity-id.../shibboleth</saml:Issuer><samlp:NameIDPolicy AllowCreate="1"/></samlp:AuthnRequest>
I believe signing info should go here as part of request. As http request, it goes as GET request, is that correct?
When I see the request in network, I can see the Signature going as query param
The status code of the request is '200'
It is not unusual to send the signature as part of the query string. Its like a pre-signed URL.
Just enabling "signing=true" on SP should not change the key that
was originally generated. So re-sending the metadata is not a
requirement. Check with IdP if the SP's metadata was originally
imported in full or did they just add relying-party and other basic end
points to integrate, that might work just fine if request signing is
not required.
If IdP is not able to verify the signature then they must be missing
the certificate from SP. To be sure compare the two metadata files
before and after enabling signing and encryption, they should
match(specially around certificates) but for the additional attribute
that you had already identified. Resend the metadata otherwise.
No other configuration changes are required in this case.

SAML 2.0 SP metadata: Purpose and the use of certificate

Here is the part of SP metadata.
Reference: Metadata for the OASIS Security Assertion Markup Language (SAML) V2.0
...
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
...
Are there any benefits to choose same (or different) certificate in both signing and encryption certificate ?
What is the purpose of including signing certificate here ?
If the message is sent through https, a transport layer encryption is provided. Do we still need to include encryption certificate here ?
In SAML 2.0 Web SSO's metadata providers typically declare the same certificate for both signing and encryption usage.
There are some use-cases where usage of different keys makes sense - e.g. when SP itself is not supposed to be able to decrypt data provided by IDP (e.g. nameID or attributes), but this is only done by the ultimate recipient of the Assertion; or when a different party provides content for creation of assertion than the party who actually creates the SAML messages - but those use-cases are rare and more relevant for other profiles than Web SSO.
The signing certificate is included in order to inform users of the metadata on how to verify messages provided by the issuer of the metadata. For example, when SP receives a message from IDP, it uses signing certificate defined in IDP's metadata in order to verify whether the message was created by the IDP and wasn't tampered with during transport.
You typically don't need to include the encryption certificate in case encryption is done on transport layer and you don't perform any encryption on message level (e.g. of whole message, assertion, nameID or attributes).

Is SAML certificate redundant?

To configure Salesforce for SAML SSO you need to upload your organization's SAML certificate (step 7 here).
At the same time, I can see that SAML certificate is part of organization IdP metadata file:
<IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="encryption">
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data>
<X509Certificate>...
</X509Certificate>
</X509Data>
</KeyInfo>
</KeyDescriptor>
...
</IDPSSODescriptor>
Doesn't that make SAML certificate upload redundant?
For SAML the certitifiate does not need to be send in any other form than metadata. Salesforce may need this for other puruposes though. The implementation may require the certificate to be installed. This is the case in OpenAM, a certificate file must then be installed in the machines java keystore