zyork
zyork

Reputation: 65

Custom Authentication Provider is not getting called Spring Security

I am trying to implement a custom AuthenticationProvider to authenticate calls to all my protected URLs. I have implemented all the methods and believe that my xml configuration is correct, but calls to protected URLs always go to the entry-point-ref class (where I throw a 401 error). This is skipping my authentication provider (I have log statements inside my authenticate method and know it is not getting called). From other posts I have learned that the supports method could be the culprit, but I have set it to always return true so this should not be my issue.

Code for my security-context:

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

    <security:http 
            use-expressions="true"
            auto-config="false"
            create-session="stateless"
            entry-point-ref="unauthorizedEntryPoint"
            authentication-manager-ref="authenticationManager">
        <security:intercept-url pattern="/User/sign_up/*" access="permitAll" />
        <security:intercept-url pattern="/User/authenticate/**" access="permitAll" />
        <security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
    </security:http>

    <authentication-manager alias="authenticationManager">
        <authentication-provider ref="customAuthenticationProvider" />
    </authentication-manager>

    <beans:bean id="customAuthenticationProvider" class="pathto:CustomAuthenticationProvider" />

    <beans:bean id="unauthorizedEntryPoint" class="pathto:UnauthorizedEntryPoint" /

Code for web.xml:

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

    The definition of the Root Spring Container shared by all Servlets and Filters -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/security-context.xml
        </param-value>
    </context-param>

    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <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>

</web-app>

UnauthorizedEntryPoint:

public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authenticationException) throws IOException, ServletException {
        System.out.println("in unauth");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failure: UnauthorizedEntryPoint Token invalid");
    }

}

AuthenticationProvider: (Currently not doing any authenticating here)

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Override
    public Authentication authenticate(Authentication auth)
            throws AuthenticationException {
        System.out.println("in authenticate");
        String username = auth.getName();
        String password = auth.getCredentials().toString();
        List<GrantedAuthority> AUTHORITIES = new ArrayList<GrantedAuthority>();
        System.out.println("username: "+username+". password: "+ password);
        if (true) { //checkPassword(password, user.getPasswords())) {
            AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER"));
            return new UsernamePasswordAuthenticationToken(auth.getName(), auth.getCredentials(), AUTHORITIES);
        }
        return null;
    }

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

Update: I am testing this using the Advanced Rest Client using parameters j_username and j_password. Is that correct or is that the problem?

Do you have any insight into what might be the problem?

Thanks!

Upvotes: 2

Views: 6681

Answers (2)

Shaun the Sheep
Shaun the Sheep

Reputation: 22742

You have no web authentication mechanism configured, hence there is nothing to invoke the authentication manager. As a result, the request always hits your authentication entry point (which is invoked for unauthenticated users) and you get the error you observe. Typically the authentication entry point will do something like redirect to a login form, or send a WWW-Authenticate header.

You need to configure something like form or basic authentication (see either the manual or the samples that come with the project). Note that you have also configured the application to be stateless, so each request needs to be authenticated.

Upvotes: 1

Efe Kahraman
Efe Kahraman

Reputation: 1438

Why don't you remove authentication-manager-ref under security:http ? You have already declared authentication-manager tag.

<security:http 
        use-expressions="true"
        auto-config="false"
        create-session="stateless"
        entry-point-ref="unauthorizedEntryPoint">
    <security:intercept-url pattern="/User/sign_up/**" access="permitAll" />
    <security:intercept-url pattern="/User/authenticate/**" access="permitAll" />
    <security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</security:http>

Besides; not a part of your problem, but just recommendation:

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

Upvotes: 1

Related Questions