SAML-Toolkits / java-saml

Java SAML toolkit
MIT License
633 stars 396 forks source link

Logout problem on ADFS #130

Closed albertogeniola closed 7 years ago

albertogeniola commented 7 years ago

Hi everyone! First of all I would like to say thank you for the great onelogin library. The job you do guys is great and allows us to use SAML SSO in our projects.

Our setup. We are using SAML SSO on a Google App Engine library (Java 8 and standard environment) against an ADFS on Windows Server 2012. The crrent version of the java library we are using is the version 2.2.0 (as maven dependency). On the ADFS, the endpoint configuration is performed via automatic metadata retrival, through ADFS wizard. After the RP is created, we switch the signature version to SHA1 (to match our configuration) and define the nameid policy to match the SAM-AccountName from AD. Please find the configuration file we are using (I've removed pkey/publickey info and urls for privacy) as follows:

onelogin.saml2.strict = true onelogin.saml2.debug = true onelogin.saml2.sp.entityid = https://{URL_OF_SERVICE_PROVIDER}/saml-sso/metadata onelogin.saml2.sp.assertion_consumer_service.url = https://{URL_OF_SERVICE_PROVIDER}/saml-sso/login onelogin.saml2.sp.assertion_consumer_service.binding = urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST onelogin.saml2.sp.single_logout_service.url = https://{URL_OF_SERVICE_PROVIDER}/saml-sso/logout onelogin.saml2.sp.single_logout_service.binding = urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect onelogin.saml2.sp.nameidformat = urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified onelogin.saml2.sp.x509cert = -----BEGIN CERTIFICATE-----\ {OMITTED FOR PRIVACY}\ -----END CERTIFICATE----- onelogin.saml2.sp.privatekey = -----BEGIN PRIVATE KEY-----\ {OMITTED FOR PRIVACY}\ -----END PRIVATE KEY----- onelogin.saml2.idp.entityid = http://{URL_OF_IDENTITY_PROVIDER}/adfs/services/trust onelogin.saml2.idp.single_sign_on_service.url = https://{URL_OF_IDENTITY_PROVIDER}/adfs/ls/ onelogin.saml2.idp.single_sign_on_service.binding = urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect onelogin.saml2.idp.single_logout_service.url = https://{URL_OF_IDENTITY_PROVIDER}/adfs/ls/?wa=wsignout1.0 onelogin.saml2.idp.single_logout_service.response.url = onelogin.saml2.idp.single_logout_service.binding = urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect onelogin.saml2.idp.x509cert = -----BEGIN CERTIFICATE-----\ {OMITTED FOR PRIVACY}\ -----END CERTIFICATE----- onelogin.saml2.security.nameid_encrypted = true onelogin.saml2.security.authnrequest_signed = true onelogin.saml2.security.logoutrequest_signed = true onelogin.saml2.security.logoutresponse_signed = true onelogin.saml2.security.want_messages_signed = onelogin.saml2.security.want_assertions_signed = true onelogin.saml2.security.sign_metadata = false onelogin.saml2.security.want_assertions_encrypted = true onelogin.saml2.security.want_nameid_encrypted = false onelogin.saml2.security.requested_authncontext = onelogin.saml2.security.onelogin.saml2.security.requested_authncontextcomparison = exact onelogin.saml2.security.want_xml_validation = true onelogin.saml2.security.signature_algorithm = http://www.w3.org/2000/09/xmldsig#rsa-sha1 onelogin.saml2.organization.name = {OMITTED} onelogin.saml2.organization.displayname = {OMITTED} onelogin.saml2.organization.url = {OMITTED} onelogin.saml2.contacts.technical.given_name = {OMITTED} onelogin.saml2.contacts.technical.email_address = {OMITTED} onelogin.saml2.contacts.support.given_name = {OMITTED} onelogin.saml2.contacts.support.email_address = {OMITTED}

The problem. The system perfectly works when performing LOGIN. However, when performing the logout, something happens on the ADFS server, which causes the following three errors.

image

image

image

Such problems are encountered when onelogin.saml2.idp.single_logout_service.url = https://{URL_OF_ADFS_EP}/adfs/ls/ .

However, we could achieve the logout feature by changing the previous parameter as follows: **onelogin.saml2.idp.single_logout_service.url = https://{URL_OF_ADFS_EP}/adfs/ls/?wa=wsignout1.0

In the latter case, the logout happens as expected but the user is never redirected back to the ServiceProvider. We have also tried to populate the onelogin.saml2.idp.single_logout_service.response.url parameter, with no luck.

From what I've understood, we should not use the "wa=wsignout1.0" option, because that regards the windows federation logout and does not actually perfom the SAML logout. Indeed, according to the saml specification, I expect the endpoint to verify the logout request and return back to the ServiceProvider with a LogoutRespose that we shold validate.

How can we make this working using the first approach and get rid of the errors encoutered when no wa=wsignout1.0 parameter is specified?

Thank you in advice and keep the good work up!

pitbulk commented 7 years ago

If you add the wa=wsignout1.0, the LogoutRequest that you are sending is ignored and ADFS start a new IdP-SLO flow, sending a LogoutRequest.

On your configuration I see that you has SLO signature enabled:

onelogin.saml2.security.logoutrequest_signed = true
onelogin.saml2.security.logoutresponse_signed = true

Based on the crypto error, I guess that ADFS has registered a wrong SP public certificate, review the value stored on ADFS.

You can use this tool to format the public cert.. and you can try validate it using

openssl x509 -in server.crt -text -noout
albertogeniola commented 7 years ago

Hi Pitbulk,

first of all thank you for your quick reply. I followed your suggestion and I've verified all the certificates in game. They seem fine to me.

The certificate installed on the ADFS (onelogin.saml2.idp.x509cert) and registered on the SP provided this output: image

The certificate installed on the SP and registered on the ADFS server (onelogin.saml2.sp.x509cert) provided this output: image

Both of them seem to be valid. Anyways, I've noticed, in my config, that I was using SHA1 as signature algorithm, while both the ADFS and certificates are issued to work with sha256. Therefore, I've changed the onelogin.saml2.security.signature_algorithm value as follows: onelogin.saml2.security.signature_algorithm = http://www.w3.org/2000/09/xmldsig#rsa-sha256

Then, I've updated the signature algorithm to be SHA256 on the ADFS (I could choose between SHA256 and SHA1). Then I've run the test again, and this time I was not even able to perform the SAML login. Error follows: image

As you can see, it seems that ADFS does not support SHA256 signature when using such algorithm. On the other hand, the lib does not support any different binding but REDIRECT.

At this point, the questions are: -> Can we use a CERTIFICATE with RSA256 signature algorithm and use the SHA1 alg instead (it seems not) -> Can we get HTTPPost binding support for logout? -> Do you see any other test we can perform to verify where the problem resides exactly with our configuration?

To be extra sure the certificate and the private key on the SP-side were OK, I did the following:

Output was: Verified OK

Therefore I guess my configuration is OK.

pitbulk commented 7 years ago

Can we get HTTPPost binding support for logout? Not supported by this toolkit, see #116

Can we use a CERTIFICATE with RSA256 signature algorithm and use the SHA1 alg instead (it seems not) I'm not an ADFS expert, but I think so

The problem is that you set a wrong value for the Signature.

http://www.w3.org/2000/09/xmldsig-more#rsa-sha256

but you may use:

http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
albertogeniola commented 7 years ago

Hi Pitbulk,

You are right, wrong copy paste, thank you for pointing that out. However, that did not solve the problem. I've been performing some more tests to help you to figure out problem.

Using the SHA256 signature and disabling Logout Request/Response signatures.

onelogin.saml2.security.logoutrequest_signed = false
onelogin.saml2.security.logoutresponse_signed = false
onelogin.saml2.security.signature_algorithm = http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
// Using key 2048bit with sign alg SHA256

Login works (as expected), Logout does not. Exception on the ADFS side, as follows: image

This is a new error and, honestly, it is confusing. I guess the error is somehow describing the issue, but I'm not aware how to fix that. Ideas are welcome.

Using the SHA1 signature and enabling Logout Request/Response signatures.

onelogin.saml2.security.logoutrequest_signed = true
onelogin.saml2.security.logoutresponse_signed = true
onelogin.saml2.security.signature_algorithm = http://www.w3.org/2000/09/xmldsig#rsa-sha1
// Using key 2048bit with sign alg SHA1

Login works (as expected), Logout does not. The exception on the ADFS side is the same as the one we were getting before. Screenshot attached. image

Even in this case I made sure the SHA1 key I used was correct, via openssl.

I wonder why the error only shows up for the Logout process, while Login works perfectly.

I would really appreciate your help here. I also suspect this issue is affecting a variety of users, since many of them simply add wa=wsignout1.0 to workaround the problem.

BTW: thank you again for spending time in reading such tedious post/issue reports. Being a developer, I know how it is.

pitbulk commented 7 years ago

Can you share the LogoutRequest sent to ADFS and give the "must provide an Issuer with no ...."

albertogeniola commented 7 years ago

Sure. I'd prefer to send it only to you rather than posting the entire thing here. Even if it is for DEVELOPMENT, I don't feel comfortable sharing this thing here. Tell me how to send it to you and I'll do it right away.

albertogeniola commented 7 years ago

I changed my mind, I've just removed the URLs. Here it is.

<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="ONELOGIN_a10b5e17-b355-43af-9efb-e3c5c0ade515" Version="2.0" IssueInstant="2017-10-26T16:51:41Z" Destination="https://adfs.{OMITTED}.com/adfs/ls/">
    <saml:Issuer>https://{OMITTED}.{OMITTED}.ga/saml-sso/metadata</saml:Issuer>
    <saml:EncryptedID>
        <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element">
            <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"></xenc:EncryptionMethod>
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
                    <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"></xenc:EncryptionMethod>
                    <xenc:CipherData>
                        <xenc:CipherValue>ciaXagwDXa3rTieyvZACdkP8ZSxAnCFBNyD9GIVygsFTms7ojIf1m+hUlTyKiy/QK1hXZQnTgV/N
Gx9ygjCN4e/DoyhxIKUuW9BQGA7Wv5qbxaZ4RPniA0axWgxDrLFWBiaDtBj77YTQiVCKxbts3j+C
bydz31ns8RoBO77TE1+AKPdCVxNjiwMAv38JQkqlpK3oo51eyRupQsEeGjOhEg1/BWqPkX1et3gH
fwT3UyXVHThap8RZX582Uj7mmaXEKcYL6pZyOafQbK4llhUuUI9zdSHa7k1RNNidX7Lwp3HLlPzX
O8VbmO19C17btqZ6SIIkqrsHg3mLOGy2BCTheQ==</xenc:CipherValue>
                    </xenc:CipherData>
                </xenc:EncryptedKey>
            </ds:KeyInfo>
            <xenc:CipherData>
                <xenc:CipherValue>t6Jv32OgfTb0F8qJZVgJFEbr41JM8sD6OnnjQMNcubIGRQGtuc9qeEHRoI2NLiaZQsoDwar6+QCj
x9Sz0RAyZXxcN+Ls2o1XwvVLyncAhNCx3ETMa+vs7FuvPHkC7gGdU4GOhpx0j7IWD4Y6pV5y7VUL
WpT4yW5U0SKP5c4Tj8RyWrYJJOKFwXaA9pC/1gpEUdtEs7MjImNLHE4EjUd8j6eDocAnKN1vwCxl
bjdWf4EIuhkGkQT0BEcqmn3pdfClNcOi0qpCVSuyY650kshft9cUkkT9H7yuL+67vAkXa4c=</xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedData>
    </saml:EncryptedID>
</samlp:LogoutRequest>
pitbulk commented 7 years ago

If you see the Issue element has no other attibute.. so that ADFS error makes no sense..

pitbulk commented 7 years ago

Based on that thread: https://social.msdn.microsoft.com/Forums/vstudio/en-US/85b1a66f-ca0b-4ed6-a32f-c8dca4fdd6c7/slo-error-msis7074-on-adfs?forum=Geneva that is an ADFS bug that shows wrong reason..

The real reason is that ADFS required a Signature and you are sending an Unsigned Logout.. so makes sense that you receive an error on scenario: "Using the SHA256 signature and disabling Logout Request/Response signatures." If you disable SP to sign Logout, you may also modify ADFS and remove signature requirement.

The other scenario fail because it seems ADFS requires SHA256 and you are sending SHA1

Have you tried SHA256 Alg + Logout Signed? Have you tried Logout Unsigned and remove signature requirement on ADFS side?

albertogeniola commented 7 years ago

Have you tried SHA256 Alg + Logout Signed? Yes, I did.

Configuration follows:

onelogin.saml2.strict =  true
onelogin.saml2.debug =  true
// ... private key and cert at 2048 SHA256RSA
onelogin.saml2.security.signature_algorithm = http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
onelogin.saml2.security.nameid_encrypted = true
onelogin.saml2.security.authnrequest_signed = true
onelogin.saml2.security.logoutrequest_signed = true
onelogin.saml2.security.logoutresponse_signed = true
onelogin.saml2.security.want_messages_signed =
onelogin.saml2.security.want_assertions_signed = true
onelogin.saml2.security.sign_metadata = false
onelogin.saml2.security.want_assertions_encrypted = true
onelogin.saml2.security.want_nameid_encrypted = false

Error on ADFS side is the same: image

albertogeniola commented 7 years ago

Have you tried Logout Unsigned and remove signature requirement on ADFS side?

On this I am not sure. Actually, I rely on the automatic features of ADFS that fetches the configuration parameters via METADATA endpoint. If that worked, then yes I did, and the error is the following: image

albertogeniola commented 7 years ago

Hi pitbulk,

in order to give you more power of debugging, I'm replicating the DEV envinronment on another machine, using brand new test certificates, so that I can post complete configuration file-logs without sanitizing them. In this way, you'll have complete visibility on what's going on. Would this help?

albertogeniola commented 7 years ago

Hi Pitbulk,

This thread has become too dirty, that is my fault. Can you please close it so I open another one from scratch, using the brand new test configuration I've set up?