cancel
Showing results for 
Search instead for 
Did you mean: 

401 Basic Auth Error

Former Member
0 Kudos

Hi,

I have a similar issue as reported here: https://wiki.hybris.com/pages/viewpage.action?pageId=228399563

Our rest service is protected using basic auth on HTTP. Using Apache JMeter with a single thread, everything works but as soon as I use 2 threads, I start getting intermittent 401 responses.

Anyone has found a solution to this? Looks like a hybris error to me.

I am using de.hybris.platform.spring.security.CoreAuthenticationProvider in the spring security XML file.

JMeter output:

1448554997720,1,HTTP Request,200,OK,Thread Group 1-2,text,true,354,2,2,1 1448554997721,2,HTTP Request,200,OK,Thread Group 1-1,text,true,354,2,2,2 1448554997722,1,HTTP Request,200,OK,Thread Group 1-2,text,true,354,2,2,1 1448554997723,1,HTTP Request,401,Unauthorized,Thread Group 1-1,text,false,1391,2,2,1 1448554997723,1,HTTP Request,401,Unauthorized,Thread Group 1-2,text,false,1391,2,2,1 1448554997724,1,HTTP Request,200,OK,Thread Group 1-1,text,true,354,2,2,1 1448554997724,1,HTTP Request,200,OK,Thread Group 1-2,text,true,354,2,2,1 1448554997725,1,HTTP Request,200,OK,Thread Group 1-1,text,true,354,2,2,1

There is also a stacktrace in the logs:

Nov 26, 2015 4:24:29 PM org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet [springmvc-web] in context with path [/app] threw exception de.hybris.platform.jalo.JaloSystemException[HY--1] at de.hybris.platform.ldap.jalo.security.user.LDAPUserPasswordCheckingStrategy.checkPassword(LDAPUserPasswordCheckingStrategy.java:59) at de.hybris.platform.jalo.user.UserManager.checkPassword(UserManager.java:1670) at de.hybris.platform.jalo.user.User.checkPassword(User.java:548) at de.hybris.platform.jalo.user.User.checkPassword(User.java:524) at de.hybris.platform.spring.security.CoreAuthenticationProvider.authenticate(CoreAuthenticationProvider.java:130) at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156) at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:177) at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:168) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at de.hybris.platform.util.RootRequestFilter.doFilter(RootRequestFilter.java:873) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at de.hybris.platform.servicelayer.web.XSSFilter.doFilter(XSSFilter.java:230) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1074) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.ArrayIndexOutOfBoundsException at sun.security.provider.DigestBase.engineUpdate(DigestBase.java:114) at sun.security.provider.MD5.implDigest(MD5.java:101) at sun.security.provider.DigestBase.engineDigest(DigestBase.java:181) at sun.security.provider.DigestBase.engineDigest(DigestBase.java:160) at java.security.MessageDigest$Delegate.engineDigest(MessageDigest.java:588) at java.security.MessageDigest.digest(MessageDigest.java:365) at de.hybris.platform.persistence.security.DigestCalculator.calculateDigest(DigestCalculator.java:83) at de.hybris.platform.persistence.security.MD5PasswordEncoder.calculateMD5(MD5PasswordEncoder.java:40) at de.hybris.platform.persistence.security.SaltedMD5PasswordEncoder.encode(SaltedMD5PasswordEncoder.java:79) at de.hybris.platform.persistence.security.SaltedMD5PasswordEncoder.check(SaltedMD5PasswordEncoder.java:126) at de.hybris.platform.jalo.user.DefaultUserPasswordCheckingStrategy.checkPassword(DefaultUserPasswordCheckingStrategy.java:25) at de.hybris.platform.ldap.jalo.security.user.LDAPUserPasswordCheckingStrategy.checkPassword(LDAPUserPasswordCheckingStrategy.java:45)

Former Member
0 Kudos

Hi Ronald, We are facing a similar error, were you able to fix this in your case?

former_member1336901
Participant
0 Kudos

Looks like a Hybris bug. The SaltedMD5PasswordEncoder is not thread-safe, but it is instantiated only once (the PasswordEncoderFactory creates one instance and caches it). It uses one DigestCalculator object which in turn uses one MessageDigest object. This will immediately run into a race condition if several threads access the encoder in parallel.

Accepted Solutions (0)

Answers (1)

Answers (1)

former_member1336901
Participant
0 Kudos

You should be able to fix it like this:

Extend the class SaltedMD5PasswordEncoder. Override calculateMD5(String plain) to do "return DigestCalculator.getInstance("MD5").calculateDigest(plain);"

Then set the property "password.encoders" to "md5=FQCN_of_your_SaltedMD5PasswordEncoder,*=de.hybris.platform.persistence.security.PlainTextPasswordEncoder"

Let me know if that works.

Former Member
0 Kudos

hi Thomas, your modification is right. The class de.hybris.platform.persistence.security.MD5PasswordEncoder wrongly keeps an instance variable of the de.hybris.platform.persistence.security.DigestCalculator class, instead you should always call DigestCalculator.getInstance to get a new one every time, particularly because the java.security.MessageDigest class that it uses is not thread safe

former_member1336901
Participant
0 Kudos

Good. Funny that this is still an issue after more than 2.5 years. :)