zyork
zyork

Reputation: 65

Autowired Service is null when trying to Autowire into custom Authentication Provider

I am trying to configure spring security with a custom Authentication Provider. However I want to autowire in a Service to take care of the actual database authentication. I have verified that it works without this autowired bean (just hardcoding in the provider). I am using SpringMVC as well in conjuction with hibernate. I am currently doing a hybrid approach with the root config (hibernate etc.) and webMVC using java annotations and spring using xml. I know that this is frowned upon, but I am in a time crunch and don't particularly want to spend time changing to java config.

My 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"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.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>

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 
            realm="Protected API"
            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:custom-filter ref="authenticationTokenFilter" position="FORM_LOGIN_FILTER" />
    </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" />

     <beans:bean id="mySuccessHandler" class="pathTo:SuccessHandler" />

    <beans:bean
        class="com.cheersuniversity.cheers.security.AuthenticationTokenFilter"
        id="authenticationTokenFilter">
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <beans:property name="postOnly" value="false" />
        <beans:property name="authenticationSuccessHandler" ref="mySuccessHandler" />
    </beans:bean>

    <!-- <context:component-scan base-package="com.cheersuniversity.cheers" />
    <context:annotation-config /> -->


</beans:beans>

CustomAuthenticationProvider: This is where the Autowired UserService is returning null on the authProvider.isValidLogin line

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserService authService;

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

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

}

UserService:

@Service
@Transactional
public class UserService {
//Auth code

}

Let me know if I should provide any more code. I have found that some people have the problem of having to scan packages. When I added that line into my security.xml, it failed on build where there was no bean found for the filterChain. From my research, this seems to be a maven problem, but it wasn't able to be fixed the way others had fixed it. I then tried with the java config below for spring security and it still has the null pointer exception

java-config (try):

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages ="correct base package")
@EnableTransactionManagement
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomAuthenticationProvider authenticationProvider;

    @Override
    protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
        authManagerBuilder.authenticationProvider(authenticationProvider);
    }
}

Please let me know if you have any insight into why this would be autowiring in as null (it is not failing when it is building, only when it is called in the authentication provider). Any help is appreciated!

UPDATE It appears that it is autowiring in, but not the correct version (the actual autowired version). Why would this be? (I figured this out by having a property value of the UserService that I set in the xml file, I then checked and it was not null. However, there still was a nullpointer at the validate line. That is extremely bizarre to me.

Upvotes: 1

Views: 5287

Answers (1)

zyork
zyork

Reputation: 65

It was because I did not include the following in my security-context.xml

<context:component-scan base-package="com.cheersuniversity.cheers" />
<context:annotation-config />

I ended up realizing that the other error (with the FilterBean not autowiring in) was a separate issue. Once I fixed that issue: see this question for the answer to that problem.

Thanks Everyone for their help!

Upvotes: 1

Related Questions