I am trying to hook up digest password handling and acegi authorization. I have managed to do this successfully with the plain text equivalent. I think I've managed to get close to the problem. When you configure the plain text acegi handler you wire in a ProviderManager.
It is the AbstractUserDetailsAuthenticationProvider (called by the AuthenticationManager) which, upon successful authentication, that actually sets the setAuthenticated(true) on the UsernamePasswordAuthenticationToken.Code:<bean id="acegiHandler" class="org.springframework.ws.soap.security.wss4j.callback.acegi.AcegiPlainTextPasswordValidationCallbackHandler"> <property name="authenticationManager" ref="authenticationManager"/> </bean> <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"> <property name="providers"> <bean class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"> <property name="userDetailsService" ref="inMemoryDaoImpl"/> </bean> </property> </bean> <bean id="wsSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor"> <property name="validationActions" value="UsernameToken"/> <property name="validationCallbackHandler"> <!--<ref local="acegiDigestPasswordHandler"/>--> <ref local="acegiHandler"/> </property> </bean> <bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl"> <property name="userMap"> <value> Ernie=Bert,ROLE_SUPERVISOR </value> </property> </bean>
In the case of AcegiDigestPasswordValidationCallbackHandler you don't wire in a AuthenticationManager so even thought the credentials are valid it is never set to authentication in acegi SecurityContext. So the authorization fails even though the Principal has the correct GrantedAuthorities.Code:protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) { // Ensure we return the original credentials the user supplied, // so subsequent attempts are successful even with encoded passwords. // Also ensure we return the original getDetails(), so that future // authentication events after cache expiry contain the details // IB this constructor sets 'authenticated' to true UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal, authentication.getCredentials(), user.getAuthorities()); result.setDetails(authentication.getDetails()); return result; }
I'm not raising this a bug yet as this could just be pilot error although I think I've followed the Reference Guide as best I can. If someone on the team agrees that this is probably a bug I'll raise it (and hopefully try to fix it too).Code:<bean id="wsSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor"> <property name="validationActions" value="UsernameToken"/> <property name="validationCallbackHandler"> <ref local="acegiDigestPasswordHandler"/> <!--<ref local="acegiHandler"/>--> </property> </bean> <bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl"> <property name="userMap"> <value> Ernie=Bert,ROLE_SUPERVISOR </value> </property> </bean> <bean id="acegiDigestPasswordHandler" class="org.springframework.ws.soap.security.wss4j.callback.acegi.AcegiDigestPasswordValidationCallbackHandler"> <property name="userDetailsService"> <ref local="inMemoryDaoImpl"/> </property> </bean>


Reply With Quote