How to specify an AuthProvider in Spring Sec 2? Trying to backport Kerb / SPNEGO ext
Hi all,
I'm backporting Mike Weisner's great Kerberos / SPNEGO extension to work with Spring Security 2.0.4 to allow SPNEGO authentication for Atlassian Crowd products. I'd use NTLM, but I have the requirement of redirecting the user to the login page if they're outside of the network, which the Kerberos / SPNEGO enables. I've been able to backport all Sprin g Security 3 classes and am able to get SSO within the network and the login form outside of the network working with the Roo Petclinic app. I run into trouble with the form login authentication provider. It worked fine for Spring Security 3, but I get into a redirect loop with Spring Security 2, and the exception generated in the console is:
Code:
org.springframework.security.providers.ProviderNotFoundException: No AuthenticationProvider found for org.springframework.security.extensions.kerberos.KerberosServiceRequestToken
at org.springframework.security.providers.ProviderManager.doAuthentication(ProviderManager.java:214)
at org.springframework.security.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:46)
at org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter.doFilter(SpnegoAuthenticationProcessingFilter.java:131)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.logout.LogoutFilter.doFilterHttp(LogoutFilter.java:89)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:864)
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:579)
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1665)
at java.lang.Thread.run(Thread.java:662)
The only line of code that I really have control over is
org.springframework.security.extensions.kerberos.w eb.SpnegoAuthenticationProcessingFilter.doFilter(S pnegoAuthenticationProcessingFilter.java:131)
where the AuthenticationManager.authenticate(authenticationR equest) method is called. However, I don't really seem to have control over how the Authentication Manager is injected...
I came across Preauthentication failing - authentication object not found in securityContextHolder but the preauth provider is already specified. Others I've come across are
http://forum.springsource.org/showth...ation-provider
and http://stackoverflow.com/questions/9...ation-provider
My config file is
Code:
<?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"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
<!-- HTTP security configurations -->
<sec:http entry-point-ref="spnegoEntryPoint">
<sec:form-login login-processing-url="/resources/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t"/>
<sec:logout logout-url="/resources/j_spring_security_logout"/>
<sec:intercept-url pattern="/owners/**" access="IS_AUTHENTICATED_FULLY" />
<sec:intercept-url pattern="/pets/**" access="IS_AUTHENTICATED_FULLY" />
<sec:intercept-url pattern="/vets/**" access="IS_AUTHENTICATED_FULLY" />
<sec:intercept-url pattern="/visits/**" access="IS_AUTHENTICATED_FULLY" />
<sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
</sec:http>
<beans:bean id="spnegoEntryPoint" class="org.springframework.security.extensions.kerberos.web.SpnegoEntryPoint" />
<beans:bean id="spnegoAuthenticationProcessingFilter"
class="org.springframework.security.extensions.kerberos.web.SpnegoAuthenticationProcessingFilter">
<custom-filter position="PRE_AUTH_FILTER" />
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="failureHandler">
<beans:bean
class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login"/>
<beans:property name="allowSessionCreation" value="true"/>
</beans:bean>
</beans:property>
</beans:bean>
<!-- Configure Authentication mechanism -->
<sec:authentication-manager alias="authenticationManager"/>
<beans:bean id="kerberosAuthenticationProvider"
class="org.springframework.security.extensions.kerberos.KerberosAuthenticationProvider">
<sec:custom-authentication-provider/>
<beans:property name="kerberosClient">
<beans:bean class="org.springframework.security.extensions.kerberos.SunJaasKerberosClient">
<beans:property name="debug" value="true"/>
</beans:bean>
</beans:property>
<beans:property name="userDetailsService" ref="dummyUserDetailsService"/>
</beans:bean>
<beans:bean id="kerberosServiceAuthenticationProvider"
class="org.springframework.security.extensions.kerberos.KerberosServiceAuthenticationProvider">
<sec:custom-authentication-provider/>
<beans:property name="ticketValidator">
<beans:bean
class="org.springframework.security.extensions.kerberos.SunJaasKerberosTicketValidator">
<beans:property name="servicePrincipal" value="spnego_test" />
<!-- Setting keyTabLocation to a classpath resource will most likely not work in a Java EE application Server -->
<!-- See the Javadoc for more information on that -->
<beans:property name="keyTabLocation" value="file:///C:\\apache-tomcat-6.0.32\\petclinic.keytab" />
<beans:property name="debug" value="true" />
</beans:bean>
</beans:property>
<beans:property name="userDetailsService" ref="dummyUserDetailsService" />
</beans:bean>
<beans:bean id="dummyUserDetailsService" class="com.springsource.petclinic.security.DummyUserDetailsService"/>
</beans:beans>
and I've tried
Code:
<beans:bean id="authenticationManager"
class="org.springframework.security.providers.ProviderManager">
<beans:property name="providers">
<beans:list>
<beans:ref local="kerberosAuthenticationProvider"/>
<beans:ref local="kerberosServiceAuthenticationProvider"/>
</beans:list>
</beans:property>
</beans:bean>
as the authentication manager declaration as well with the same results.
This may very well be a Spring Security 2 issue that I'm unaware of -- I'm new to Spring Security and any help on what I need to do to set the AuthenticationProvider on the AuthenticationManager to get this resolved would be greatly appreciated.