1
votes

I am migrating my application's security to Spring Security 4.0 . My requirement is authentication should be JAAS authentication and Autorization data would be fetched from database. SO I have written and custom authentication provider. But my problem is Spring is not delegating authentication requests to my custom authentication provider.

Codes are given below

Custom Authentication Provider

public class CustomAutenticationProvider extends DaoAuthenticationProvider implements AuthenticationProvider {
private AuthenticationProvider delegate;

public CustomAutenticationProvider(AuthenticationProvider delegate) {
    this.delegate = delegate;
}

@Override
public Authentication authenticate(Authentication authentication) {
    Authentication a = delegate.authenticate(authentication);

    if(a.isAuthenticated()){
        a = super.authenticate(a);
    }else{
        throw new BadCredentialsException(messages.getMessage(
                "AbstractUserDetailsAuthenticationProvider.badCredentials",
                "Bad credentials"));
    }

    return a;
}

private List<GrantedAuthority> loadRolesFromDatabaseHere(String name) {
    GrantedAuthority grantedAuthority =new JaasGrantedAuthority(name, new UserPrincipal(name));
    return Arrays.asList(grantedAuthority);
}

@Override
public boolean supports(Class<?> authentication) {
    return delegate.supports(authentication);
}

/* (non-Javadoc)
 * @see org.springframework.security.authentication.dao.DaoAuthenticationProvider#additionalAuthenticationChecks(org.springframework.security.core.userdetails.UserDetails, org.springframework.security.authentication.UsernamePasswordAuthenticationToken)
 */
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails,
        UsernamePasswordAuthenticationToken authentication)
                throws AuthenticationException {


    if(!authentication.isAuthenticated())
        throw new BadCredentialsException(messages.getMessage(
                "AbstractUserDetailsAuthenticationProvider.badCredentials",
                "Bad credentials"));


}

}

Load Authorization Data

public class CustomUserDetailsService implements UserDetailsService {

private UserDataSource _dataSource = UserDataSource.newInstance();

/* (non-Javadoc)
 * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
 */
@Override
public UserDetails loadUserByUsername(String username)
        throws UsernameNotFoundException {
    System.out.println("loadUserByUsername with param: "+username+" called");
    int _userID;
    UserData _userData = null;
    try {
        _userID = _dataSource.findUserID( username );
        _userData = _dataSource.findByID( _userID );
    } catch (SystemException | SecurityException e) {
        throw new BackEndSystemException("Could not retrieve userId or UserData for userName :"+username);
    }

    return _userData;
}

}

Spring XML entry

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">


<security:authentication-manager id="customAuthManager">
        <security:authentication-provider ref="customauthProvider" />
    </security:authentication-manager>
    <bean id="customauthProvider" class="com.enterprise.security.CustomAutenticationProvider">
        <constructor-arg name="delegate" ref="jaasAuthProvider" />
        <property name="userDetailsService" ref="userDetailsService" />
    </bean>

    <security:http pattern="*/js/**" security="none" />
    <security:http pattern="*/css/**" security="none" />
    <security:http pattern="*/image*" security="none" />
    <security:http pattern="/en/Login*" security="none" />
    <security:http auto-config="true" use-expressions="true">
        <security:csrf disabled="true" />
        <security:intercept-url pattern="/**" access="permitAll" />
        <security:form-login login-page="/en/Login.jsp" default-target-url="/en/account/AccountWelcome.jsp" />
        <security:logout invalidate-session="true" delete-cookies="JSESSIONID" logout-success-url="/en/account/AccountWelcome.jsp" logout-url="/j_spring_security_logout" />
        <!-- 
            <security:session-management session-fixation-protection="newSession"> 
                <security:concurrency-control max-sessions="1" expired-url="/loginfailed"  error-if-maximum-exceeded="false"/> </security:session-management>
        -->
    </security:http>

    <bean id="userDetailsService" class="com.enterprise.security.service.CustomUserDetailsService"></bean>

    <bean id="jaasAuthProvider"
    class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
        <property name="loginConfig" value="classpath:ldap.jaas.config" />
        <property name="authorityGranters">
            <list>
                <bean class="com.enterprise.security.DummyJAASRoleGrantor" />
            </list>
        </property>
        <property name="loginContextName" value="LDAPLogin" />
        <property name="callbackHandlers">
            <list>
                <bean
                    class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler" />
                <bean
                    class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler" />
            </list>
        </property>
    </bean>
</beans>

web.xml entry

    <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xmlns="http://java.sun.com/xml/ns/javaee"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
             id="WebApp_ID" version="3.0">

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/springApplicationContext.xml
        </param-value>
    </context-param>
      
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>
            org.springframework.web.filter.DelegatingFilterProxy
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

Call Stack

Daemon Thread [http-bio-8080-exec-9] (Suspended (breakpoint at line 29 in CustomUserDetailsService))    
owns: SocketWrapper<E>  (id=407)    
CustomUserDetailsService.loadUserByUsername(String) line: 29    
DaoAuthenticationProvider.retrieveUser(String, UsernamePasswordAuthenticationToken) line: 114   
DaoAuthenticationProvider(AbstractUserDetailsAuthenticationProvider).authenticate(Authentication) line: 143 
ProviderManager.authenticate(Authentication) line: 167  
ProviderManager.authenticate(Authentication) line: 192  
UsernamePasswordAuthenticationFilter.attemptAuthentication(HttpServletRequest, HttpServletResponse) line: 93    
UsernamePasswordAuthenticationFilter(AbstractAuthenticationProcessingFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 217   
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 330 
LogoutFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 120   
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 330 
HeaderWriterFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 64  
HeaderWriterFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107   
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 330 
WebAsyncManagerIntegrationFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 53    
WebAsyncManagerIntegrationFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107 
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 330 
SecurityContextPersistenceFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 91    
FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 330 
FilterChainProxy.doFilterInternal(ServletRequest, ServletResponse, FilterChain) line: 213   
FilterChainProxy.doFilter(ServletRequest, ServletResponse, FilterChain) line: 176   
DelegatingFilterProxy.invokeDelegate(Filter, ServletRequest, ServletResponse, FilterChain) line: 344    
DelegatingFilterProxy.doFilter(ServletRequest, ServletResponse, FilterChain) line: 261  
ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 241  
ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 208  
StandardWrapperValve.invoke(Request, Response) line: 220    
StandardContextValve.invoke(Request, Response) line: 122    
NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 505    
StandardHostValve.invoke(Request, Response) line: 170   
ErrorReportValve.invoke(Request, Response) line: 103    
AccessLogValve.invoke(Request, Response) line: 957  
StandardEngineValve.invoke(Request, Response) line: 116 
CoyoteAdapter.service(Request, Response) line: 423  
Http11Processor(AbstractHttp11Processor<S>).process(SocketWrapper<S>) line: 1079    
Http11Protocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler<S,P>).process(SocketWrapper<S>, SocketStatus) line: 620   
JIoEndpoint$SocketProcessor.run() line: 318 
ThreadPoolExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker) line: 1145  
ThreadPoolExecutor$Worker.run() line: 615   
TaskThread$WrappingRunnable.run() line: 61  
TaskThread(Thread).run() line: 724  
1
I cannot see CustomAutenticationProvider registered any where within spring security xml .. Is that delibrate for some reason ? - ArunM
It is there. Some how missed in copy-paste. I have updated the xml - Debopam
Based on some other configuration it has been observed that spring is not using my custom authentication provider at all. It is using DAOAuthenticationProvider by default though it is initializing the bean. - Debopam

1 Answers

0
votes

I have missed alias attribute in authentication manager. But why this alias is necessary?

<security:authentication-manager alias="authenticationManager">
        <security:authentication-provider ref="customauthProvider" />
</security:authentication-manager>