Reputation: 65
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
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
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