Loading…
Tilbage
×

Info

Der findes en nyere version af resourcen her

oiosaml.java 2.0.6


OIOSAML for Java release 2.0.6 has been made available. This release contains the following changes

  • Fixed issue with validating SAMLResponse from IdP's that signed both the Response and Assertion object, as well as encrypted the Assertion object [1]
  • Fixed issue where OIOSAML did not correctly validate the signature on an Assertion element if the Response element was signed
  • Fixed unittests to correctly sign the Assertion element, and not the Response element

[1] The issue fixed is discussed in detail here: https://www.digitaliser.dk/resource/2298008#comment_2905121

Note that OIOSAML.java previously allowed unsigned Assertion elements if the Response element was signed. This is no longer the case, as the OIOSAML specification requires the Assertion element to be signed, and OIOSAML.java now enforces this requirement.

Code repository

The code is still available through Softwarebørsen SVN, and can be located here

https://svn.softwareborsen.dk/oiosaml.java/oiosaml2/

Maven repository

The binary artifacts are distributed as Maven dependencies, and can be located here

https://mvnrepository.com/artifact/dk.digst/oiosaml2.java

Profilbillede

Developer-mode: Response from oiosaml is already commited

Mads Vering

Upgrading from oiosaml-21188.java to oiosaml-2.0.6.java.

Test and production mode seems to work out just fine.

However, in developermode, I get this error (i did not get that before upgrading):

java.lang.IllegalStateException: Cannot call forward() after response has been committed
	org.apache.catalina.connector.ResponseFacade.reset(ResponseFacade.java:347)
	myapp.nemlogin.LoginServlet.doPost(LoginServlet.java:360)
	myapp.nemlogin.LoginServlet.doGet(LoginServlet.java:185)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	dk.itst.oiosaml.sp.develmode.DevelModeImpl.doFilter(DevelModeImpl.java:110)
	dk.itst.oiosaml.sp.service.SPFilter.doFilter(SPFilter.java:167)

As the stacktrace shows, the response is passed to my own LoginServlet and from there forwarded to my own application (but this fails in developermode). Did you accidentally do some to the response in developermode in the new oiosaml?

 

Hi Mads.

There should be no changes to the DevelMode code, but that doesn't not mean that it could not be an indirect consequence of the changes.

The error message indicates that something has already been send to the client (browser), somewhere previous in the flow, and the attempt to write to the client then causes this error (I assume LoginServlet.java:360 attempts to perform some operation on the HttpServletResponse object).

It is a bit tricky to figure out where exactly in the flow this happens without actively debugging, but while looking at the DevelModeImpl class, I noticed a bug in line 101. The code performs a sendRediect() call on the HttpServletResponse object, without stopping the code execution (a return statement) - this means the flows continues, and potentially reaches your code, at which point it fails, because a response has already been send to the client.

Why exactly it enters that bit of the code (line 101) would require active debugging, but if you can, try stepping through the code to see if it reaches that statement - as it would be the cause of the error that you see.

In all cases, I'll make sure to fix this issue in DevelModeImpl.

It does not explain why the code execution flow has changed since your upgrade though, that probably requires a bit more insight. If you can recompile oiosaml yourself, it might be worth it to add a return statement after line 101 in DevelModeImpl.java, and see what happens - it might give you all the information you need (the response send to the client probably contains the reason for the aborted flow).

Hi Brian

Thanks for quick reply. Actually, it seems incorrect, that the DevelModelImpl does a sendRedirect() in line 101 at all. I made a check where I only have a single development-user (normally I have 15 users). In that case line 101 is not executed (there is a check for the number of users in line 83), and then everything works as it should.

Also the line 100 is redundant, as the SESSION_USER_ASSERTION is being set in line 106. 

So it seems line 100 and 101 should just be deleted, and no extra return statement should be added.

ændret af Mads Vering (06.06.2018)
Profilbillede

ValidationException: Invalid signature

Yuhao Rui

After upgraded to OIOSAML2 2.0.6,  it throws out following exception after logout.

It looks like the second bug that is claimed fixed in this release. 

 

dk.itst.oiosaml.sp.model.validation.ValidationException: Invalid signature
at dk.itst.oiosaml.sp.model.OIOLogoutResponse.validate(OIOLogoutResponse.java:227)
at dk.itst.oiosaml.sp.service.LogoutHTTPResponseHandler.handleGet(LogoutHTTPResponseHandler.java:74)
at dk.itst.oiosaml.sp.service.DispatcherServlet.doGet(DispatcherServlet.java:193)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:286)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:260)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:137)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:350)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:25)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78)

Hi Yuhao,

the stacktrace indicates the the signature validation fails on a LogoutResponse from the Identity Provider. The change in this release should not affect validation on the LogoutResponse, as this is isoluated in the Utils.java class, which uses the build-in Signature class in java to perform both a sha-1 based signature validation and a sha-256 based signature validation, and if one of them passes, it is happy - so no change as far as I can see since the previous releases.

Best guess is that the signature is either invalid, or the signature was performed using a certificate that is not trusted by the service provider.

 

Hi Brian

First, thank you for your quick reply.

I will try to explain a bit more details:

Before NemLog-in switched from SHA1 to SHA-256, we were using OIOSAML 21188, which worked well until the switch. So it is hard to understand if our certificate is suddenly not trusted by SP.

After the switch, we upgraded from 21188 to version 2.0.2, it starts to have the mentioned issue.

We have also tried all the versions from 2.0.2 to 2.0.6, they all end up the same. So for us, the problem is not only on version 2.0.6.

Could the reason be that the new version of OIOSAML enforces Assertion element to be signed in in signed response?

Hi Yuhao.

The stacktrace is on validation of the signature on the LogoutResponse, so it has nothing to do with the signature validation on the Assertion.

Can you explain from the top what is happening? What is done in the browser, what happens in the flow, and when does the error occur?

I assume something like this

  1. The user accesses your web-application, and clicks "login"
  2. The user is redirect to NemLog-in, and performs a login
  3. The user is redirected back to your web-application, and can now use the application
  4. After a while, the user decides to logout, and clicks your logout button
  5. The user is redirected to NemLog-in, which performs single-logout on all other applications the user is signed into
  6. The user is finally redirected back to your web-application, with a signed response from NemLog-in
  7. The web-application fails validating the response, with the mentioned error

Is the above correct?

 

Hi Brian

These are exactly the steps.

Here are some logs during some of these steps. Hope you could see something from them.

 

  1. The user is redirected to NemLog-in, which performs single-logout on all other applications the user is signed into

https://login.test-nemlog-in.dk/adfs/ls/?SAMLRequest=fVLRjpswEPwVy89ZMIYkYIWcktBIqOm1uqRV1ZfKwYa4ATvF5nT39wUuOfUq9d68u57ZmdEu7p6aGj3K1iqjUxx4BCOpCyOUrlL89bCFGN8tF5Y3Nb2wnalM5x7k705ah3qktuxllOKu1cxwqyzTvJGWuYLtV592jHqEXVrjTGFqjLIeqDR347aTcxfLfL82ldKe60egZdNX0Jfi7HNRWr%2B2PkZ5luKfUyqPdE5mcAyLEqKARHCkVEAxL4UMZrIsRa8%2Bt7aTubaOa5diSoIYegiZHQLKQsqixJvHwQ%2BMHiS3g4j3dNejX9ZZ2WL07RYSHUL6y%2Fz7HNz26MEvvsbIRoXt8uZ%2BaHqtKTvbiUfPXlRdy%2BZZC1WdpJBDEAv%2FDfBKc9%2BvyjO0NW3D3f81BF4wdpSAcvzKvk9Jsu%2BOv2ThBg683KTZx8nnNNeV1Mi0FdfKcmdaZc%2FIqfqsn53u72GyuU8PJ2mOvBZox7tWOSv1ZC9bxev0S56xhJIYKCEUKBASxSSZxck0JjcDL5Jfz2kv7ZBoroV8WoZbCAms57D%2BACsK0xWEMcQRRCtYr4FsYRrBLIZgA0kMSTi8yRw2GWSrK%2F0%2FhK%2FdN1e7%2FAM%3D&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=OMfBVOiDC6ilbDtpDJVyYDQY7%2BJN0ZsCRUuIwpVxS6pD1yIggN9OgA5orEIbK0m%2Ff1E4uAyN5TWQwMNZrlv6U%2FowF48j8dgUtKj2sHqL3y3WC0XK1UXWIxd%2FazhMC%2BlVDFltEVgbKMD6r%2FhiPnL%2BeEk0JaGqK13%2BoCxZ9j0abj0Rj3%2BKQlebm%2BN9sq7yNlPAgXteWDXEqZ47K7slnVNMwsCIk810SqoNZcGiJocbxO4OrRmC1RYqypZ%2BjUQWzGTRaeCybkb26wMKfKYNFgVP5RSBKyCWmzTT7q8jov38RjviqgPMt6x7mhI4VWzmfdxMko3oEErhVnEP4oZk3N9IMQ%3D%3D

 

 

  1. The user is finally redirected back to your web-application, with a signed response from NemLog-in

https://test-nemlog-in.dk/IDP.ashx?SAMLRequest=fVLRjpswEPwVy89ZMIYkYIWcktBIqOm1uqRV1ZfKwYa4ATvF5nT39wUuOfUq9d68u57ZmdEu7p6aGj3K1iqjUxx4BCOpCyOUrlL89bCFGN8tF5Y3Nb2wnalM5x7k705ah3qktuxllOKu1cxwqyzTvJGWuYLtV592jHqEXVrjTGFqjLIeqDR347aTcxfLfL82ldKe60egZdNX0Jfi7HNRWr%2B2PkZ5luKfUyqPdE5mcAyLEqKARHCkVEAxL4UMZrIsRa8%2Bt7aTubaOa5diSoIYegiZHQLKQsqixJvHwQ%2BMHiS3g4j3dNejX9ZZ2WL07RYSHUL6y%2Fz7HNz26MEvvsbIRoXt8uZ%2BaHqtKTvbiUfPXlRdy%2BZZC1WdpJBDEAv%2FDfBKc9%2BvyjO0NW3D3f81BF4wdpSAcvzKvk9Jsu%2BOv2ThBg683KTZx8nnNNeV1Mi0FdfKcmdaZc%2FIqfqsn53u72GyuU8PJ2mOvBZox7tWOSv1ZC9bxev0S56xhJIYKCEUKBASxSSZxck0JjcDL5Jfz2kv7ZBoroV8WoZbCAms57D%2BACsK0xWEMcQRRCtYr4FsYRrBLIZgA0kMSTi8yRw2GWSrK%2F0%2FhK%2FdN1e7%2FAM%3D&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&Signature=OMfBVOiDC6ilbDtpDJVyYDQY7%2BJN0ZsCRUuIwpVxS6pD1yIggN9OgA5orEIbK0m%2Ff1E4uAyN5TWQwMNZrlv6U%2FowF48j8dgUtKj2sHqL3y3WC0XK1UXWIxd%2FazhMC%2BlVDFltEVgbKMD6r%2FhiPnL%2BeEk0JaGqK13%2BoCxZ9j0abj0Rj3%2BKQlebm%2BN9sq7yNlPAgXteWDXEqZ47K7slnVNMwsCIk810SqoNZcGiJocbxO4OrRmC1RYqypZ%2BjUQWzGTRaeCybkb26wMKfKYNFgVP5RSBKyCWmzTT7q8jov38RjviqgPMt6x7mhI4VWzmfdxMko3oEErhVnEP4oZk3N9IMQ%3D%3D

  1. The web-application fails validating the response, with the mentioned error

https://rofusudv.spillemyndigheden.dk/saml/LogoutServiceHTTPRedirectResponse?SAMLResponse=jZJRS8MwFIX%2fSsl72iarmwtdQRziQEG24YMvkiY3W7BNRm4q%2bu%2fNOir4MoTADZd7cr9zSP3kD36IW8CTdwjZZr0i7%2fxWtmDYLeVtW9JSzRldMrWkC9O20ihuSqNJ9goBrXcrwvOSZBvEATYOo3QxtcqkLufp7BkXMy6qZb5cVIyx6o1ka8BonYyj%2bhjjCUVRBG8GHPRnjifbddB%2fO20PR9Dgcv1RoOy74sK6g%2fBpFTzu9y9b0DaA%2bsVPGG66731ycsOh5YsE0s6UoRUrK9pyrqlaGA1sDsboxP7Vdw5XZAhOeIkWhZM9oIhK7O6en0TyJ07BR698R5p6dBqyBx96Ga%2brzh2rqRlHBbho4%2fe%2f1klECOd8SDPlc04gjyk56qDv%2fIHaMZi6uPA09S7KOOBU772G7FV2A1zfhOO02A1KASLJiqYuppeKv5%2bj%2bQE%3d&SigAlg=http%3a%2f%2fwww.w3.org%2f2001%2f04%2fxmldsig-more%23rsa-sha256&Signature=ghg3RAACBc9glVF7SmdtKZEPuuy%2fV4MWySO7HcIs33PVsxR7HtLSPQz8xjSLs%2f0F%2bfcoUQN0iMkHukRjKVQzllPj5nWrhyglzj0Pf3Gt6VokfLeVlHO6vKsBq8Sztvo9bT8Psug8%2bQUyEixtzhuOqoSxN7s2HYuZlC8dkxfzvI%2bXFyMuUvq%2f5RpbsK7uqspTOn%2bvHtUx19KY%2b4PjlGCpx4JEoQzQvqwvqfphvumknLkfLjptKoYmRgzJu61ZbMcs62lRhpX4oGKl6UuVaGoixPkhrSXxIbhk234%2bcxyqAxlm6bxUfX%2b2HPCpIU3U0BYrutRLHil1xAa5fPVz6q03%2bQ%3d%3d

 

2018-06-06 14:32:50,495 INFO - LOGOUTREQUEST <-- 10.9.250.1 phbVFCoBuNOvdpf4c2n4YhK58R4hBXXL4-7eqpTuCQeimzQPXbx9!-604632092!1528288258561 '' '<?xml version="1.0" encoding="UTF-8"?><LogoutResponse xmlns="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://rofusudv.spillemyndigheden.dk/saml/LogoutServiceHTTPRedirectResponse" ID="_28abef18-2bb0-0c61-91c9-7fbbafc2f0fd" InResponseTo="_52eb2706-b3cf-4104-b22d-c7fde16effd0" IssueInstant="2018-06-06T12:32:49.9741114Z" Version="2.0"><Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://saml.test-nemlog-in.dk/</Issuer><Status><StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></Status></LogoutResponse>' 'RequestID _52eb2706-b3cf-4104-b22d-c7fde16effd0'
2018-06-06 14:32:50,502 ERROR - Dispatch:LogoutServiceHTTPRedirectResponse <-- 10.9.250.1 phbVFCoBuNOvdpf4c2n4YhK58R4hBXXL4-7eqpTuCQeimzQPXbx9!-604632092!1528288258561 '' '' 'Invalid signature'
dk.itst.oiosaml.sp.model.validation.ValidationException: Invalid signature
at dk.itst.oiosaml.sp.model.OIOLogoutResponse.validate(OIOLogoutResponse.java:227)
at dk.itst.oiosaml.sp.service.LogoutHTTPResponseHandler.handleGet(LogoutHTTPResponseHandler.java:74)
at dk.itst.oiosaml.sp.service.DispatcherServlet.doGet(DispatcherServlet.java:193)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:286)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:260)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:137)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:350)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:25)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78)

A bit more from oiosaml-sp-audit.log:

 

[2018-06-06 14:58:00,729] [INFO ] [[ACTIVE] ExecuteThread: '9' for queue: 'weblogic.kernel.Default (self-tuning)'] [OIOSAML_AUDIT_LOGGER] LOGOUT --- 10.9.250.1 LEzVLEYnfaqICNQxc1G6pIntb5_KXrE9_w2wSJLrXD7VnSjmVjTs!-604632092!1528289838631 '_e89deddd-f654-47f9-86bc-a9e42db0ff05' '' 'C=DK,O=Ingen organisatorisk tilknytning,CN=Theobald Lauritsen,Serial=PID:9208-2002-2-004809689580'
[2018-06-06 14:58:01,068] [INFO ] [[ACTIVE] ExecuteThread: '9' for queue: 'weblogic.kernel.Default (self-tuning)'] [OIOSAML_AUDIT_LOGGER] Session created at: 1528289838631, timeout after 3600 seconds
[2018-06-06 14:58:01,079] [INFO ] [[ACTIVE] ExecuteThread: '9' for queue: 'weblogic.kernel.Default (self-tuning)'] [OIOSAML_AUDIT_LOGGER] LOGOUTREQUEST <-- 10.9.250.1 LEzVLEYnfaqICNQxc1G6pIntb5_KXrE9_w2wSJLrXD7VnSjmVjTs!-604632092!1528289838631 '' '<?xml version="1.0" encoding="UTF-8"?><LogoutResponse xmlns="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://rofusudv.spillemyndigheden.dk/saml/LogoutServiceHTTPRedirectResponse" ID="_4d9a622f-2c3a-3977-b3ad-b93b4f14439e" InResponseTo="_1107cb9e-2426-4f5c-a48e-cf439f245c6d" IssueInstant="2018-06-06T12:58:00.8846818Z" Version="2.0"><Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://saml.test-nemlog-in.dk/</Issuer><Status><StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></Status></LogoutResponse>' 'RequestID _1107cb9e-2426-4f5c-a48e-cf439f245c6d'
[2018-06-06 14:58:01,081] [ERROR] [[ACTIVE] ExecuteThread: '9' for queue: 'weblogic.kernel.Default (self-tuning)'] [OIOSAML_AUDIT_LOGGER] Dispatch:LogoutServiceHTTPRedirectResponse <-- 10.9.250.1 LEzVLEYnfaqICNQxc1G6pIntb5_KXrE9_w2wSJLrXD7VnSjmVjTs!-604632092!1528289838631 '' '' 'Invalid signature'
dk.itst.oiosaml.sp.model.validation.ValidationException: Invalid signature
at dk.itst.oiosaml.sp.model.OIOLogoutResponse.validate(OIOLogoutResponse.java:227)
at dk.itst.oiosaml.sp.service.LogoutHTTPResponseHandler.handleGet(LogoutHTTPResponseHandler.java:74)
at dk.itst.oiosaml.sp.service.DispatcherServlet.doGet(DispatcherServlet.java:193)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:286)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:260)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:137)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:350)
at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:25)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78)

Can you debug the application? I'm curious as to how the verifySignature() method found in Utils.java executes.

As part of supporting SHA-256, the following very simple logic was implemented in Utils.java, which is used when validating a logout response

  1. Attempt to validate signature using SHA1
  2. If it fails (throws a SignatureException), attempt to validate using SHA256

This was to avoid a large rewrite of the existing code-logic, as the information about the signature algorithm was not passed through the layers (unlike the login scenario, where we have all the information available).

So I'm guessing that in your case, it fails on the SHA1 validation, but it does not throw a SignatureException, thus bypassing the SHA256 backup-check.

This might be because your using weblogic (I just noticed the stacktrace), and it changes the underlying crypto-provider, which might behave in a different way than the standard java provider.

It is a bit of a guess, as the contract for the Signature class states it should throw a SignatureException in case of a bad signature, but I've seen bad behaviour from 3rd party implementations before.

https://docs.oracle.com/javase/7/docs/api/java/security/Signature.html#verify(byte[])

Vi har nu debugget logout’en med step into alting i java på vores oracle weblogic på en solaris server.

Den eneste detour den tager til 3’de part software er til com.oracle.security.ucrypto

Den kan ikke bypasses på solaris (Ifølge vores service provider).

Når den returnerer til logout koden OIOLogoutResponse kaster den i linie 227 en ValidationException pga invalid signature

Som bliver fanget af DispatcherServlet.java linie 194

Som håndterer fejlen.

Så den kommer aldrig til jeres catch (SignatureException ex) og får derfor ikke testet op mod sha-256 da det allerede er gået galt.

Good.

I'll probably do both (perform SHA-256 first, as that is now the default), and then keep a more robust fallback to SHA-1, as there are users of the OIOSAML framework that does not use it with NemLog-in, and they might still use SHA-1.

I'll make sure an official 2.0.7 release is available soon.

Hi Thomas.

If you can build OIOSAML from source, I've comitted a more robust handler for dealing with SHA-256. It now catches all exceptions when attempting to do a sha-1 based validation, and if either an exception occurs, or the validation itself fails with a returnvalue = false, then it attempts a SHA-256 validation.

It should be as easy as

$ svn co https://svn.softwareborsen.dk/oiosaml.java/oiosaml2/trunk/oiosaml/

$ cd oiosaml

$ mvn clean install

Which should install oiosaml into your local repository - then build your application and test again. Let me know if it works - I'll make sure the fix is part of the next release.

I'm not sure i'm allowed to change and recompile your code.

But maybe i can get permission to do it on our dev environment.

A quick fix would be to swap line 144 and 151 in Utils.java

I would even claim that after wednesday nobody should call with SHA1 the check will always fail and cause the error. (When applicable).

I'm also afraid that changing the exception catch scope won't prevent the dispathcer from eating it first.

Hi Thomas.

I'd prefer not to release an official oiosaml build unless I'm sure it fixes your issue, but if there are policies in place that prevents you from running on un-released versions of OIOSAML, I'll see what I can do with regards to doing an unofficial release that you can test on ;)

There is noone that says that the release MUST have a final version number, it could be 2.0.7-rc1 or something like that ;)

Hi Brian

The fix(swap line 144 and 151 in Utils.java) Thomas suggests works well for us.