Ankit
Ankit

Reputation: 2256

spring security custom authentication not working

I am running a web application build on spring security version 4.2, spring mvc version 4.2. I want to run customAuthenticationProvider and customAuthenticationSuccessHandler, but customAuthenticationProvider class is not getting called and Request is going to only authentication-failure-url

pom.xml

          <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>4.2.0.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>4.2.0.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>4.2.0.RELEASE</version>
            </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.2.0.RELEASE</version>
        </dependency>

        <!-- Spring Security Jars starts-->
        <!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>4.2.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>4.2.0.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>4.2.0.RELEASE</version>
        </dependency>
        <!-- Spring Security Jars ends-->

application-security.xml

<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.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd">

    <http pattern="/resources/css/**" security="none"/>
    <http pattern="/resources/img/**" security="none"/>
    <http pattern="/resources/js/**" security="none"/>



    <http auto-config="false" use-expressions="true"> 
<!--    <intercept-url pattern="/onemoretime/*" access="hasRole('ROLE_ADMIN')"/>-->
        <intercept-url pattern="/admin/*" access="permitAll"/>
        <intercept-url pattern="/vendor/*" access="permitAll"/>
        <form-login login-page="/login"         
                    username-parameter="username"
                    password-parameter="password"
                    authentication-success-handler-ref="customAuthenticationSuccessHandler"
                    authentication-failure-url="/accessdenied"
                    />

        <!-- <logout logout-success-url="/login"/>       -->    
         <csrf />
    </http>

    <authentication-manager alias="authenticationProvider">
        <authentication-provider ref="myAuthenticationProvider"/> 

    </authentication-manager>

    <!-- Bean implementing AuthenticationProvider of Spring Security -->
    <beans:bean id="myAuthenticationProvider" class="com.opstree.vendorportal.authentication.CustomAuthenticationProvider"/>

    <beans:bean id="customAuthenticationSuccessHandler" class="com.opstree.vendorportal.authentication.CustomAuthenticationSuccess"/>

</beans:beans>

web.xml

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:/service.xml /WEB-INF/application-security.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
    <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>

loginpage.jsp

    <form action="${pageContext.request.contextPath}/login" method="post">
        <table>
            <tr>
                <td>UserName</td>
                <td><input type="text" name="username"></td>
            </tr>
            <tr>
                <td>Password</td>
                <td><input type="password" name="password"> </td>
            </tr>
            <tr>
                <td align="center" colspan="2">
                    <div style="color:red" class="servererror">
                        <c:if test="${not empty userobject}">
                            <b><c:out value="${userobject.message}"></c:out></b>
                        </c:if>
                    </div>
                </td>
            </tr>
            <tr>
                <td align="center" colspan="2">
                    <input type="submit" value="Login">
                </td>
            </tr>
            <tr>
                <td align="center" colspan="2">
                    <b><a href="forgotpassword">ForgotPassword</a></b>
                </td>
            </tr>
            <tr>
                <td align="center" colspan="2">
                    <b>Click here to <a href="registerVendor">Register</a></b>
                </td>
            </tr>
        </table>
        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    </form>

customAuthenticationProvider

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDBOperationsImpl userDAO;

    private Logger logger = Logger.getLogger(getClass());

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        System.out.println("Spring Security: Entered");
        UsernamePasswordAuthenticationToken  authenticationToken = (UsernamePasswordAuthenticationToken) authentication;
        String username = authenticationToken.getName();
        //String password = (String) authenticationToken.getCredentials();

        UserBean userBean = null;

        try {
            userBean =  userDAO.getUserDetails(username);
        } catch (Exception e) {
            logger.error(e.getCause().getMessage());
        }

        if(userBean == null){
            throw new BadCredentialsException("Invalid Credentials");
        }
        List<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));

        Authentication auth = new UsernamePasswordAuthenticationToken(userBean, userBean.getPassword(), authorities);

        System.out.println("Exit");
        return auth;
    }

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

customAuthenticationSuccess

public class CustomAuthenticationSuccess implements AuthenticationSuccessHandler {

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth)
            throws IOException, ServletException {
        System.out.println("Entered Authentication Successful Method");
        boolean isUser = false;
        Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
        String targetUrl = null;
        for(GrantedAuthority currentAuth : authorities){
            if(currentAuth.getAuthority().equalsIgnoreCase("ROLE_USER")){
                isUser = true;
                break;
            }
            else {
                throw new IllegalStateException();
            }
        }

        if(isUser){
            targetUrl = "/vendor";
        }
        System.out.println("Entered Authentication Successful Method");
        redirectStrategy.sendRedirect(request, response, targetUrl);
    }
}

Upvotes: 0

Views: 3002

Answers (1)

jlumietu
jlumietu

Reputation: 6444

I think that what is happening is that the supports(Class<?> authentication) method in your AuthenticationProvider is not correctly implemented.

You are checking the Authentication class received against your CustomAuthenticationProvider getClass() method, so as it allways would return false, the AuthenticationManager will not recognize your provider as a suitable provider for the received UsernamePasswordAuthenticationToken.

You can check org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider code in github where you could see that a correct implementation for this method in a UsernamePasswordAuthenticationToken supporting provider should be this way:

public boolean supports(Class<?> authentication) {
    return (UsernamePasswordAuthenticationToken.class
            .isAssignableFrom(authentication));
}

What I guess is actually happening is that the AuthenticationManager cannot find a UsernamePasswordAuthenticationToken supporting provider, so the authentication cannot be performed, and the unauthorized Authentication is getting to UsernamePasswordAuthenticationFilter which finally has nothing to do but redirect to the authentication-failure-url.

Be carefull too with your AuthenticationSuccessHandler, the way you are checking the GranthedAuthorities might end with a IllegalStateException in case the first GranthedAuthority evaluated is not the ROLE_USER one:

        for(GrantedAuthority currentAuth : authorities){
            if(currentAuth.getAuthority().equalsIgnoreCase("ROLE_USER")){
                isUser = true;
                break;
            }
            else {
                throw new IllegalStateException();
            }
        }

Upvotes: 1

Related Questions