In a webapp using the pac4j dependency to implement SSO support, I encounter an issue.
Context:
Java EE/JRE 1.7.0.79, Tomcat 7.0.70, org.springframework:spring:3.2.16.RELEASE, org.springframework.security:spring-security-core:3.2.9.RELEASE, org.pac4j:spring-security-pac4j:1.4.1, org.pac4j:pac4j-oauth:1.8.3, org.pac4j:pac4j-saml:1.8.3
Multiple 3rd-party authentication providers are enabled in the webapp configuration (say Google OAuth and any SAML), forwarded to UI as 2 buttons on the login page: "Login with Google", "Login with my_SAML_provider_label"
Requirements:
Upgrading Java or/and Tomcat is an option. Upgrading spring and pac4j is not
Do not use Spring annotations injection, anytime possible
Issue enduser-sequence:
1/ Click "Login with Google" (useragent is redirected to Google's authentication page)
2/ Authenticate properly on the Google page, with an outer-user that will or will not match any of your local app users upon callback
3/ Go back to the local webapp login page
4/ Click "Login with my_SAML_provider_label" now (useragent is redirected to the provider authentication page)
5/ Authenticate properly on the 3rd-party page, with an outer-user that will or will not match any of your local app users upon callback
6/ Assert the following exception in logs: org.pac4j.oauth.profile.google2.Google2Profile cannot be cast to org.pac4j.saml.profile.SAML2Profile
Issue stacktrace:
java.lang.ClassCastException: org.pac4j.oauth.profile.google2.Google2Profile cannot be cast to org.pac4j.saml.profile.SAML2Profile
at com.company.module.sso.SAMLAuthenticationService.retrieveAuthenticatedUser(SAMLAuthenticationService.java:59)
..
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:507)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.company.module.filters.ApplicationAvailabilityFilter.doFilter(ApplicationAvailabilityFilter.java:59)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.company.module.filters.LogFilter.doFilter(LogFilter.java:57)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.company.module.filters.ChronoFilter.doFilter(ChronoFilter.java:78)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.company.module.filters.HibernateFilter.doFilter(HibernateFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
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:106)
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:343)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
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:218)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:442)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1082)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:623)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Related sourcecode:
applicationContext-security.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
..
<beans:bean id="clientFilter" class="org.pac4j.springframework.security.web.ClientAuthenticationFilter">
<beans:constructor-arg value="/outer-authentication"/>
<beans:property name="clients" ref="clients" />
<beans:property name="sessionAuthenticationStrategy" ref="sas" />
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
..
<beans:bean id="sas" class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy" />
</beans:beans>
SAMLAuthenticationService.java:
..
ClientAuthenticationToken token = null;
try {
token = (ClientAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
final SAML2Profile samlProfile = (SAML2Profile) token.getUserProfile(); // L59
..
} finally {
token.eraseCredentials(); // troubleshooting: not clearing credentials made no difference
}
..
Observations:
The same issue can be obtained by first attempting a login through the SAML provider, then through the Google one: the user-sequence order seems irrelevant
A workaround is to stop Tomcat, clean its work directory, then restart it
Either way is to wait for the initial authentication token (callbacked/obtained from provider 1) to expire (expiration delay set to 1h through the pac4j configuration I/O)
Issue will bump again, as soon as the faulty sequence is performed again by the enduser
Guess:
Related to an improper revocation of the authentication token of the previous SSO authentication (callbacked/obtained from provider 1), before attempting to read the authentication token of the current authentication process (callbacked/obtained from provider 2)
Indirectly, due to an improper use of org.springframework.security.web.authentication.session.SessionAuthenticationStrategy (my implementation in the Spring Security XML configuration seems standard/defaults)
Thanks
Solved it seems: Spring security's SecurityContextHolder.clearContext(); must have been being invoked, before any situation where a jump from one provider to another one may occur.
Such situations may be:
the remote-user was successfuly authenticated by the SSO provider but matches no local-user
the local-user is already signed on the local-app through an SSO provider, but browsed or got redirected to the local-app homepage, and may then attempt an SSO authentication through another SSO provider
the local-user asked or got redirected to the logout URL: while destroying the web session, this should also clear the Spring security's context
I did not test concurrency scenarios yet (1 local-user authenticating through different browsers through different SSO providers, multiple users), so even if I can assert the initial issue is solved, that may still have side-effects (dropping the intended-user context (desired), but also other users contexts (undesired)).
User authentication exists within 1 session, while the security context exists within 1 thread. So I'm a bit lost in order to get the proper grip on it.
Related
I am hitting http://localhost:5000/hello to get com.sap.cloud.sdk.cloudplatform.security.user.User & com.sap.cloud.sdk.cloudplatform.connectivity.Destination objects after xsuaa login.
Occurred below exception while getting destination after xsuaa login in locally.
Please find my non-working code from github
approuter URL: http://localhost:5000
businessapp URL: http://localhost:8080/businessapp
Please suggest me how to fix this issue.
com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException: com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException: Failed to get destinations of provider service instance: Failed to get access token for destination service. If your application is running on Cloud Foundry, make sure to have a binding to both the destination service and the authorization and trust management (xsuaa) service, AND that you either properly secured your application or have set the "ALLOW_MOCKED_AUTH_HEADER" environment variable to true. If your application is not running on Cloud Foundry, for example, when deploying to a local container, consider declaring the "destinations" environment variable to configure destinations.
at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationFacade.getGenericDestinationsByName(ScpCfDestinationFacade.java:202)
at com.sap.cloud.sdk.cloudplatform.connectivity.AbstractDestinationFacade.getGenericDestination(AbstractDestinationFacade.java:173)
at com.sap.cloud.sdk.cloudplatform.connectivity.AbstractDestinationFacade.getDestination(AbstractDestinationFacade.java:191)
at com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor.getDestination(DestinationAccessor.java:202)
at com.dama.scpcf.services.DestinationService.getDestination(DestinationService.java:10)
at com.dama.scpcf.web.HelloWorldServlet.doGet(HelloWorldServlet.java:45)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at com.google.inject.servlet.ServletDefinition.doServiceImpl(ServletDefinition.java:287)
at com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:277)
at com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:182)
at com.google.inject.servlet.ManagedServletPipeline.service(ManagedServletPipeline.java:91)
at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:85)
at com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:119)
at com.google.inject.servlet.GuiceFilter$1.call(GuiceFilter.java:133)
at com.google.inject.servlet.GuiceFilter$1.call(GuiceFilter.java:130)
at com.google.inject.servlet.GuiceFilter$Context.call(GuiceFilter.java:203)
at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:130)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.sap.cloud.sdk.cloudplatform.servlet.RequestContextServletFilter.lambda$doFilter$0(RequestContextServletFilter.java:171)
at com.sap.cloud.sdk.cloudplatform.servlet.RequestContextCallable.call(RequestContextCallable.java:95)
at com.sap.cloud.sdk.cloudplatform.servlet.RequestContextServletFilter.doFilter(RequestContextServletFilter.java:173)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.sap.cloud.sdk.cloudplatform.security.servlet.HttpCachingHeaderFilter.doFilter(HttpCachingHeaderFilter.java:57)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.sap.cloud.sdk.cloudplatform.security.servlet.HttpSecurityHeadersFilter.doFilter(HttpSecurityHeadersFilter.java:42)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.filters.RestCsrfPreventionFilter.doFilter(RestCsrfPreventionFilter.java:115)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:176)
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:357)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
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.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:436)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2517)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2506)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.google.common.util.concurrent.UncheckedExecutionException: com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException: Failed to get destinations of provider service instance: Failed to get access token for destination service. If your application is running on Cloud Foundry, make sure to have a binding to both the destination service and the authorization and trust management (xsuaa) service, AND that you either properly secured your application or have set the "ALLOW_MOCKED_AUTH_HEADER" environment variable to true. If your application is not running on Cloud Foundry, for example, when deploying to a local container, consider declaring the "destinations" environment variable to configure destinations.
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2050)
at com.google.common.cache.LocalCache.get(LocalCache.java:3951)
at com.google.common.cache.LocalCache$LocalManualCache.get(LocalCache.java:4870)
at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationFacade.getGenericDestinationsByName(ScpCfDestinationFacade.java:180)
... 75 more
Caused by: com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException: Failed to get destinations of provider service instance: Failed to get access token for destination service. If your application is running on Cloud Foundry, make sure to have a binding to both the destination service and the authorization and trust management (xsuaa) service, AND that you either properly secured your application or have set the "ALLOW_MOCKED_AUTH_HEADER" environment variable to true. If your application is not running on Cloud Foundry, for example, when deploying to a local container, consider declaring the "destinations" environment variable to configure destinations.
at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationFacade.buildDestinationAccessException(ScpCfDestinationFacade.java:299)
at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationFacade.fetchAllDestinations(ScpCfDestinationFacade.java:233)
at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationFacade.lambda$getGenericDestinationsByName$0(ScpCfDestinationFacade.java:183)
at com.google.common.cache.LocalCache$LocalManualCache$1.load(LocalCache.java:4875)
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3527)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2276)
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2154)
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2044)
... 78 more
Caused by: java.util.concurrent.ExecutionException: Observable onError
at rx.internal.operators.BlockingOperatorToFuture$2.getValue(BlockingOperatorToFuture.java:118)
at rx.internal.operators.BlockingOperatorToFuture$2.get(BlockingOperatorToFuture.java:102)
at com.netflix.hystrix.HystrixCommand$4.get(HystrixCommand.java:423)
at com.sap.cloud.sdk.cloudplatform.connectivity.ScpCfDestinationFacade.fetchAllDestinations(ScpCfDestinationFacade.java:229)
... 84 more
Caused by: com.netflix.hystrix.exception.HystrixRuntimeException: com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceCommand#t=52d1f6b0-fd5c-44ad-bbf2-f33ff148c780#u= failed and fallback disabled.
at com.netflix.hystrix.AbstractCommand.handleFallbackDisabledByEmittingError(AbstractCommand.java:1052)
at com.netflix.hystrix.AbstractCommand.getFallbackOrThrowException(AbstractCommand.java:878)
at com.netflix.hystrix.AbstractCommand.handleFailureViaFallback(AbstractCommand.java:1034)
at com.netflix.hystrix.AbstractCommand.access$700(AbstractCommand.java:60)
at com.netflix.hystrix.AbstractCommand$12.call(AbstractCommand.java:622)
at com.netflix.hystrix.AbstractCommand$12.call(AbstractCommand.java:601)
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$2.onError(AbstractCommand.java:1194)
at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.onError(OperatorSubscribeOn.java:80)
at rx.observers.Subscribers$5.onError(Subscribers.java:230)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at rx.observers.Subscribers$5.onError(Subscribers.java:230)
at com.netflix.hystrix.AbstractCommand$DeprecatedOnRunHookApplication$1.onError(AbstractCommand.java:1431)
at com.netflix.hystrix.AbstractCommand$ExecutionHookApplication$1.onError(AbstractCommand.java:1362)
at rx.observers.Subscribers$5.onError(Subscribers.java:230)
at rx.observers.Subscribers$5.onError(Subscribers.java:230)
at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:44)
at rx.internal.operators.OnSubscribeThrow.call(OnSubscribeThrow.java:28)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.unsafeSubscribe(Observable.java:10327)
at rx.internal.operators.OperatorSubscribeOn$SubscribeOnSubscriber.call(OperatorSubscribeOn.java:100)
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:56)
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:47)
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction.call(HystrixContexSchedulerAction.java:69)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
... 1 more
Caused by: com.sap.cloud.sdk.cloudplatform.connectivity.exception.DestinationAccessException: Failed to get access token for destination service.
at com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceCommand.getAccessToken(DestinationServiceCommand.java:114)
at com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceCommand.run(DestinationServiceCommand.java:124)
at com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceCommand.run(DestinationServiceCommand.java:28)
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:302)
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:298)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
... 26 more
Caused by: com.sap.cloud.sdk.cloudplatform.security.exception.TokenRequestFailedException: com.sap.cloud.sdk.cloudplatform.exception.NoServiceBindingException: Failed to get "destination" service credentials: no service binding found . Please make sure to correctly bind your application to a service instance.
at com.sap.cloud.sdk.cloudplatform.connectivity.XsuaaService.getClientCredentials(XsuaaService.java:133)
at com.sap.cloud.sdk.cloudplatform.connectivity.XsuaaService.getServiceToken(XsuaaService.java:231)
at com.sap.cloud.sdk.cloudplatform.connectivity.DestinationServiceCommand.getAccessToken(DestinationServiceCommand.java:111)
... 31 more
Caused by: com.sap.cloud.sdk.cloudplatform.exception.NoServiceBindingException: Failed to get "destination" service credentials: no service binding found . Please make sure to correctly bind your application to a service instance.
at com.sap.cloud.sdk.cloudplatform.ScpCfCloudPlatform.getServiceCredentials(ScpCfCloudPlatform.java:331)
at com.sap.cloud.sdk.cloudplatform.ScpCfCloudPlatform.getServiceCredentials(ScpCfCloudPlatform.java:244)
at com.sap.cloud.sdk.cloudplatform.connectivity.XsuaaService.getClientCredentials(XsuaaService.java:130)
... 33 more
Essentially, the preconditions to make that run are named in the error message.
Failed to get destinations of provider service instance: Failed to get
access token for destination service. If your application is running
on Cloud Foundry, make sure to have a binding to both the destination
service and the authorization and trust management (xsuaa) service,
AND that you either properly secured your application or have set the
"ALLOW_MOCKED_AUTH_HEADER" environment variable to true. If your
application is not running on Cloud Foundry, for example, when
deploying to a local container, consider declaring the "destinations"
environment variable to configure destinations.
So make sure that both environment variables are set as expected.
Find more information about the destinationsvariable in step 4 of our blog posts.
As described by Emdee you can mock the destination using the ALLOW_MOCKED_AUTH_HEADER variable. However, using this variable will also render the local access to a JWT-based user as answered here useless: Failed to get current user: no RequestContext available.
Alternatively, you have to provide the configuration to the destination service via VCAP_SERVICES similar to the XSUAA configuration as answered here: Invalid bean definition with name 'offlineTokenServices' defined in ServletContext resource [/WEB-INF/spring-security.xml] based on a real service binding in CloudFoundry. Please use cf env <yourappname> to copy those values from a bound application in CF to your local setup. Disclaimer: I did not try it myself, but it should work this way.
In my current implementation of Spring Secutity SAML extension version 1.0.1.RELEASE, the passive login gives me a stack trace. I want to validate a (possibly) logged in user when the user fires a request.
My entryPoint is defined as:
<security:http entry-point-ref="samlEntryPoint">
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
<security:custom-filter ref="metadataGeneratorFilter" before="FIRST"/>
<security:custom-filter ref="samlFilter" after="BASIC_AUTH_FILTER"/>
</security:http>
The entryPoint itself is
<bean id="samlEntryPoint" class="org.springframework.security.saml.SAMLEntryPoint">
<property name="defaultProfileOptions">
<bean class="org.springframework.security.saml.websso.WebSSOProfileOptions">
<property name="includeScoping" value="false"/>
<property name="passive" value="true" />
</bean>
</property>
</bean>
When requesting a passive login the SAML tracker shows me this (omitted several parts not interesting)
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
Destination="URI"
IssueInstant="2015-11-24T10:32:06.864Z"
Version="2.0"
>
...
<saml2p:Status>
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:NoPassive" />
</saml2p:Status>
</saml2p:Response>
Console output is as follows
24 nov 2015 11:32:04 INFO (org.springframework.security.saml.metadata.MetadataGeneratorFilter:108) - No default metadata configured, generating with default values, please pre-configure metadata for production use
24 nov 2015 11:32:04 INFO (org.springframework.security.saml.metadata.MetadataGeneratorFilter:130) - Created default metadata for system with entityID: http://localhost/webshop
24 nov 2015 11:32:04 INFO (org.springframework.security.saml.log.SAMLDefaultLogger:127) - AuthNRequest;SUCCESS;0:0:0:0:0:0:0:1;http://localhost/webshop;IDPENDPOINT;;;
24 nov 2015 11:32:07 INFO (org.opensaml.common.binding.security.BaseSAMLSimpleSignatureSecurityPolicyRule:130) - Validation of request simple signature succeeded
24 nov 2015 11:32:07 INFO (org.opensaml.common.binding.security.BaseSAMLSimpleSignatureSecurityPolicyRule:132) - Authentication via request simple signature succeeded for context issuer entity ID IDPENDPOINT
24 nov 2015 11:32:07 INFO (org.opensaml.common.binding.security.SAMLProtocolMessageXMLSignatureSecurityPolicyRule:129) - Validation of protocol message signature succeeded, message type: {urn:oasis:names:tc:SAML:2.0:protocol}Response
And the following stacktrace
24 nov 2015 11:32:09 INFO (org.springframework.security.saml.log.SAMLDefaultLogger:127) - AuthNResponse;FAILURE;0:0:0:0:0:0:0:1;http://localhost/webshop;IDPENDPOINT;;;org.opensaml.common.SAMLException: Response has invalid status code urn:oasis:names:tc:SAML:2.0:status:NoPassive, status message is null
at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:113)
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:82)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:87)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:211)
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:166)
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.saml.metadata.MetadataGeneratorFilter.doFilter(MetadataGeneratorFilter.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:343)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at nl.ns.soaplogger.logging.filter.LogSoapFilter.doFilter(LogSoapFilter.java:61)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.sitemesh.webapp.contentfilter.ContentBufferingFilter.bufferAndPostProcess(ContentBufferingFilter.java:169)
at org.sitemesh.webapp.contentfilter.ContentBufferingFilter.doFilter(ContentBufferingFilter.java:126)
at nl.ns.decorator.GenericFrontEndFilter.doFilter(GenericFrontEndFilter.java:51)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:440)
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:943)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
As seen the status code for the message is urn:oasis:names:tc:SAML:2.0:status:NoPassive, which (according to the idp supplier) indicates that the user is not logged in. In our case, we want to serve the application to the user without any pre filled details.
When following the stacktrace, we can see the line on which the error is thrown, and the preceding lines.
AuthnRequest request = null;
SAMLObject message = context.getInboundSAMLMessage();
// Verify type
if (!(message instanceof Response)) {
throw new SAMLException("Message is not of a Response object type");
}
Response response = (Response) message;
// Verify status
String statusCode = response.getStatus().getStatusCode().getValue();
if (!StatusCode.SUCCESS_URI.equals(statusCode)) {
StatusMessage statusMessage = response.getStatus().getStatusMessage();
String statusMessageText = null;
if (statusMessage != null) {
statusMessageText = statusMessage.getMessage();
}
throw new SAMLException("Response has invalid status code " + statusCode + ", status message is " + statusMessageText);
}
SUCCESS_URI has the following value in StatusCode (from the OpenSAML project)
String SUCCESS_URI = "urn:oasis:names:tc:SAML:2.0:status:Success";
Am I doing something wrong in the code concerning passive logins (it works for non-passives) or is there simply no support (yet) for the given status code by the IDP?
i start a new project with spring-boot and oauth. I try to secure some url of my project.
Here my Httpsecurty config:
http.authorizeRequests()
.antMatchers("/test")
.access("#oauth2.hasRole('USER')")
and i have this configuration too for my clientdetailsserviceconfigurer:
clients.inMemory()
.withClient("xxxxx")
.authorizedGrantTypes("password", "refresh_token")
.authorities("USER")
.scopes("read")
.resourceIds(RESOURCE_ID)
.secret("sssss")
I registred an user with the role "USER" and i received an access_token from the server. But when i try to access the /test/ url with this token, i got this execption
java.lang.IllegalArgumentException: Failed to evaluate expression '#oauth2.throwOnError(#oauth2.hasRole('USER'))'
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:13)
at org.springframework.security.web.access.expression.WebExpressionVoter.vote(WebExpressionVoter.java:34)
at org.springframework.security.web.access.expression.WebExpressionVoter.vote(WebExpressionVoter.java:18)
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:62)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:206)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:176)
And when i try it without the #oauth2 argument:
.access("hasRole('USER')")
, i got:
type=AUTHORIZATION_FAILURE, data={type=org.springframework.security.access.AccessDeniedException, message=Access is denied}]
has someone any ideas?
Thanks
Cheers
I know the issue is very old, But fortunately the solution .access("hasRole('USER')") helped me. Well thanks for the help.
But for others (learning spring security) let me share my knowledge on the issue, It seems like the user with which you're trying to login doesn't have access to that role, So check your db (USER_ROLE) if that user has that role associated. Because in my scenario I was checking for Admin role and when I tried to login with the non-admin user the same error 'Access Denied' appeared for me.
Try to set the WebExpressionVoter's expressionHandler to be an instance of OAuth2WebSecurityExpressionHandler:
webExpressionVoter.setExpressionHandler(new OAuth2WebSecurityExpressionHandler());
You can also try to use .hasRole( "USER" ) instead of your .access(...).
I'm trying to setup SSO for Java WebApp using Kerberos/SpNego.
I'm using:
Java 1.7u67
org.springframework.security.kerberos 1.0.0.RELEASE
Active Directory
Tomcat 7 on Linux
After overcoming the problem discribed in How to configure kerberos on Tomcat/linux server?, I'm now stuck with the following error:
org.springframework.security.authentication.BadCredentialsException: Kerberos validation not succesful
at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:70) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
at org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider.authenticate(KerberosServiceAuthenticationProvider.java:64) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156) ~[spring-security-core-3.2.7.RELEASE.jar:3.2.7.RELEASE]
at org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.java:145) ~[spring-security-kerberos-web-1.0.0.RELEASE.jar:1.0.0.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [spring-security-web-3.2.7.RELEASE.jar:3.2.7.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.55]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.55]
at org.lightadmin.core.view.TilesContainerEnrichmentFilter.doFilterInternal(TilesContainerEnrichmentFilter.java:40) [lightadmin-1.2.0.RC1.jar:1.2.0.RC1]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.55]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.55]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.55]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.55]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) [catalina.jar:7.0.55]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [catalina.jar:7.0.55]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) [catalina.jar:7.0.55]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) [catalina.jar:7.0.55]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) [catalina.jar:7.0.55]
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) [catalina.jar:7.0.55]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [catalina.jar:7.0.55]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) [catalina.jar:7.0.55]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070) [tomcat-coyote.jar:7.0.55]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611) [tomcat-coyote.jar:7.0.55]
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316) [tomcat-coyote.jar:7.0.55]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_67]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_67]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-coyote.jar:7.0.55]
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_67]
Caused by: java.security.PrivilegedActionException: null
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.7.0_67]
at javax.security.auth.Subject.doAs(Subject.java:415) ~[na:1.7.0_67]
at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator.validateTicket(SunJaasKerberosTicketValidator.java:67) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
... 42 common frames omitted
Caused by: org.ietf.jgss.GSSException: Failure unspecified at GSS-API level (Mechanism level: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - RC4 with HMAC)
at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:788) ~[na:1.7.0_67]
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:342) ~[na:1.7.0_67]
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285) ~[na:1.7.0_67]
at sun.security.jgss.spnego.SpNegoContext.GSS_acceptSecContext(SpNegoContext.java:875) ~[na:1.7.0_67]
at sun.security.jgss.spnego.SpNegoContext.acceptSecContext(SpNegoContext.java:548) ~[na:1.7.0_67]
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:342) ~[na:1.7.0_67]
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285) ~[na:1.7.0_67]
at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:162) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
at org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator$KerberosValidateAction.run(SunJaasKerberosTicketValidator.java:152) ~[spring-security-kerberos-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
... 45 common frames omitted
Caused by: sun.security.krb5.KrbException: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - RC4 with HMAC
at sun.security.krb5.KrbApReq.authenticate(KrbApReq.java:273) ~[na:1.7.0_67]
at sun.security.krb5.KrbApReq.<init>(KrbApReq.java:144) ~[na:1.7.0_67]
at sun.security.jgss.krb5.InitSecContextToken.<init>(InitSecContextToken.java:108) ~[na:1.7.0_67]
at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:771) ~[na:1.7.0_67]
... 53 common frames omitted
However it seems that the key should be there, since on startup of the application I got the following debug:
Debug is true storeKey true useTicketCache false useKeyTab true doNotPrompt true ticketCache is null isInitiator false KeyTab is /opt/pksvc/tomcat_edl/current/conf/TestSpnego.keytab refreshKrb5Config is false principal is TestSpnego#MYREALM.DE tryFirstPass is false useFirstPass is false storePass is false clearPass is false
principal is TestSpnego#MYREALM.DE
Will use keytab
>>> KeyTabInputStream, readName(): MYREALM.DE
>>> KeyTabInputStream, readName(): HTTP
>>> KeyTabInputStream, readName(): lxdetstpksvc01.mydomain.de
>>> KeyTab: load() entry length: 83; type: 23
Ordering keys wrt default_tkt_enctypes list
Java config name: /opt/pksvc/tomcat_edl/current/conf/krb5.conf
Loaded from Java config
default etypes for default_tkt_enctypes: 23.
Commit Succeeded
So enctype 23 = RC4 with HMAC is the type of the KeyTab entry and the default enctype.
I can also see that the browser sends a token with this enctype (I removed the binary part from the following):
Ticket TicketType{TktVno=5,Realm=MYREALM.DE,Sname=HTTP/lxdetstpksvc01.mydomain.de,EncPart=EncryptedData{Etype=23,Kvno=4,Cipher=binary[... 352 16728 KerberosV5.TicketType
Authenticator EncryptedData{Etype=23,Kvno=nothing,Cipher=binary[... 17080 2872 KerberosV5.EncryptedData
So everything seems to be encytpe 23 (RC4 with HMAC). When I had a look at the code I found that sun.security.krb5.EncryptionKey which is used by KrbApReq (which throws the error in the stack above) is indeed not only comparing the enctype, but also the version. So I guess that is what must be wrong in my case.
In the ticket above is Kvno=4 for EncryptedData and for Authenticator EncryptedData it is Kvno=nothing. Should these match?
How can I resolve this? Is this influenced by the generation of the keytab?
It turned out the error above resulted from two problems:
The service principal in the spring configuration was wrong. It was
lxdetstpksvc01.mydomain.de#MYREALM.DE, but
HTTP/lxdetstpksvc01.mydomain.de#MYREALM.DE is correct.
The Kvno in the keytab was not identical with the Kvno stored in the
active directory. As stated on
https://tomcat.apache.org/tomcat-7.0-doc/windows-auth-howto.html
Active Directory is raising the Kvno with every execution of ktpass.
However I wasn't able to find the value (msDS-KeyVersionNumber) for
it in our AD and could only grap it from the request.
Summarized the 'Cannot find key of appropriate type to decrypt ...' error can result from one of the following problems:
The service prinicpal in the spring security configuration is not identical with that from the keytab (param /princ from ktpass).
There is no key for the enctype the AD has send the ticket with (param /crypto from ktpass and set in the krb5.conf/permitted_enctypes+default_tkt_enctypes).
The Kvno from the ticket is different then the Kvno in the keytab (param /kvno from ktpass).
The path to the keytab is wrong (see answer from Xavier Portebois)
The process does not have permissions to read the keytab (See comment from user7610)
We also got a Invalid argument (400) - Cannot find key of appropriate type to decrypt ... error.
This can simply be thrown if the path to the keytab is wrong (in our case, we forgot we got a docker volume mapping there).
So, be sure the keytab path is the right one, as this could fire this weird exception.
If you are using Spring Boot then please pay attention how you specify keytab file.
Note that the classpath: it will work when you run spring-boot:run
However it wont when you run java -jar xyz.jar Because JAAS cant read it from classpath.
So please prefer file: while specifying keytab file path.
(This is typical case when you use docker to package and run your application)
This can also be thrown if your using Active Directory as the KDC and the keytab user is configured for a different encryption setting than your keytab is using. In my case AES 128 was configured and I was expecting AES 256. A simple change of the configuration within AD resolved the issue.
In my case, the jaas config file of the server needed the parameter "storeKey" set to true.
The service prinicpal in the spring security configuration is not identical with that from the keytab (param /princ from ktpass).
In my case they were the same, but param /princ was not correct.
HTTP and domain part must be uppercase.
Correct example:
HTTP/service.example.lan#EXAMPLE.LAN
Incorrect example:
http/service.example.lan#Eexample.lan
I've been struggling with this during 4 hours
the parameter "storeKey" set to true in the jaas file resolved the issue
I had the same error because the keytab file was generated with the wrong /crypto configuration.
Failure unspecified at GSS-API level (Mechanism level: Invalid argument (400) Cannot find key of appropriate type to decrypt AP-REQ - RC4 with HMAC)
Generate a new keytab file using /crypto ALL with the ktpass command:
ktpass /out "server.keytab" /crypto ALL /princ HTTP/server#REALM /mapuser KERBEROS_SERVICEUSER /pass PASSWORD /ptype KRB5_NT_PRINCIPAL
Replace HTTP/server#REALM, KERBEROS_SERVICEUSER and PASSWORD with according values.
In my case, I got the below log,
WARN SpnegoAuthenticationProcessingFilter:149 - Negotiate Header was invalid: Negotiate XXX
org.springframework.security.authentication.BadCredentialsException: Kerberos validation not successful
Caused by: java.security.PrivilegedActionException: GSSException: Failure unspecified at GSS-API level (Mechanism level: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - AES256 CTS mode with HMAC SHA1-96)
Caused by: GSSException: Failure unspecified at GSS-API level (Mechanism level: Invalid argument (400) - Cannot find key of appropriate type to decrypt AP REP - AES256 CTS mode with HMAC SHA1-96)
and it was a permission issue.
The executing user didn't have the permission to read the keytab file, so I changed the permission with chmod command.
I am getting error while decryption of saml token. However this issue is not consistent it works after restarting server. It was working properly till last night :(
DEBUG Decrypter:631 - Attempt to decrypt EncryptedKey using credential from KEK KeyInfo resolver failed:
org.opensaml.xml.encryption.DecryptionException: Probable runtime exception on decryption:unknown parameter type.
at org.opensaml.xml.encryption.Decrypter.decryptKey(Decrypter.java:705)
at org.opensaml.xml.encryption.Decrypter.decryptKey(Decrypter.java:628)
at org.opensaml.xml.encryption.Decrypter.decryptUsingResolvedEncryptedKey(Decrypter.java:783)
at org.opensaml.xml.encryption.Decrypter.decryptDataToDOM(Decrypter.java:524)
at org.opensaml.xml.encryption.Decrypter.decryptDataToList(Decrypter.java:442)
at org.opensaml.xml.encryption.Decrypter.decryptData(Decrypter.java:403)
at org.opensaml.saml2.encryption.Decrypter.decryptData(Decrypter.java:141)
at org.opensaml.saml2.encryption.Decrypter.decrypt(Decrypter.java:69)
at org.springframework.security.saml.websso.WebSSOProfileConsumerImpl.processAuthenticationResponse(WebSSOProfileConsumerImpl.java:199)
at org.springframework.security.saml.SAMLAuthenticationProvider.authenticate(SAMLAuthenticationProvider.java:82)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
at org.springframework.security.saml.SAMLProcessingFilter.attemptAuthentication(SAMLProcessingFilter.java:84)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:195)
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:166)
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.saml.metadata.MetadataGeneratorFilter.doFilter(MetadataGeneratorFilter.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:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
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.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: unknown parameter type.
at org.bouncycastle.jce.provider.JCERSACipher.engineInit(Unknown Source)
at javax.crypto.Cipher.implInit(Cipher.java:791)
at javax.crypto.Cipher.chooseProvider(Cipher.java:849)
at javax.crypto.Cipher.init(Cipher.java:1348)
at javax.crypto.Cipher.init(Cipher.java:1282)
at org.apache.xml.security.encryption.XMLCipher.decryptKey(XMLCipher.java:1475)
at org.opensaml.xml.encryption.Decrypter.decryptKey(Decrypter.java:697)
... 41 more
09:21:51,120 ERROR Decrypter:639 - Failed to decrypt EncryptedKey, valid decryption key could not be resolved
09:21:51,120 DEBUG Decrypter:787 - Attempt to decrypt EncryptedData using key extracted from EncryptedKey faile
Earlier I was getting invalide key size error which I fixed with the help of
Spring SAML ADFS: java.security.InvalidKeyException. However I am not sure whether it will have any impact on US security policy law.
But this decrypt exception is not getting resolved and its not consistent. Some time it starts working after restarting server.
I tried each and everything in last 2-3 days. I thought issue occurs after metadata refresh so I tried adding below property to ResourceBackedMetadataProvider bean but no luck.
<property name="parserPool" ref="parserPool"/>
<property name="minRefreshDelay" value="120000"/>
<property name="maxRefreshDelay" value="300000"/>
Then i debug WebSSOProfileConsumerImpl.java code thought this mught be the issue related to jira so I checkout the latest code and create new jar and added to my project but no luck.
After spending one week in debugging and googling, I have decide to fix this issue with a little hack.
I checked out Spring-Saml source code from Master branch of gitHub Repository and build jar and import it into my project. I thought this SES-144 issue is similar to mine, so I tried with latest code but no luck.
So I decided to to debug xmlTooling.jar code and find the exact point of failure and overwrote the below method decryptKey(EncryptedKey encryptedKey, String algorithm) in XMLCipher.java with below code.
Cipher c = constructCipher(encryptedKey.getEncryptionMethod()
.getAlgorithm(), encryptedKey.getEncryptionMethod()
.getDigestAlgorithm());
Instead of calling
c.init(4, key, oaepParameters);
used below code and removed if/else block
c.init(4, key);
You can checkout the custom jars from github
You need to update your saml dependency with below lines in pom.xml file to use this custom jar
<dependency>
<groupId>org.springframework.security.extensions</groupId>
<artifactId>spring-security-saml2-core</artifactId>
<version>1.0.1.RELEASE</version>
<exclusions>
<exclusion>
<artifactId>xmlsec</artifactId>
<groupId>org.apache.santuario</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<artifactId>xmlsec</artifactId>
<groupId>org.apache.santuario</groupId>
<version>1.5.6-custom</version>
</dependency>
If anyone find better solution please let me know.