简体   繁体   中英

How do I set up PreAuthenticationAuthenticationProvider?

I've been trying to get OAuth 2 working for my application but I continue running into configuration-related errors, specifically involving authentication tokens. The application is set up to act as both authorization and resource server. I've successfully configured it to issue tokens using password grant type, with an in-memory token store. However, every time I try to send requests for restricted resources, I get errors saying:

org.springframework.security.authentication.ProviderNotFoundException: No AuthenticationProvider found for org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken

So, I tried setting up a PreAuthenticationAuthenticationProvider in my configuration:

@Autowired
private UserDetailsManager userManager;

@Bean
public AuthenticationProvider preAuthenticationAuthenticationProvider() {
    PreAuthenticatedAuthenticationProvider authenticationProvider =
        new PreAuthenticatedAuthenticationProvider();
    UserDetailsByNameServiceWrapper userDetailsWrapper = new UserDetailsByNameServiceWrapper(userManager);
    authenticationProvider.setPreAuthenticatedUserDetailsService(userDetailsWrapper);
    return authenticationProvider;
}

However, I'm getting NullPointerException in weird places, like:

java.lang.NullPointerException: null
    at org.springframework.security.authentication.AccountStatusUserDetailsChecker.check(AccountStatusUserDetailsChecker.java:17) ~[spring-security-core-4.0.3.RELEASE.jar!/:4.0.3.RELEASE]

I'm wondering what the simplest configuration for this is, and why I need it in the first place? Is it because I have @PreAuthorize annotations?

Here's how I set up the resource server:

@Configuration
protected static class ResourceServer extends ResourceServerConfigurerAdapter {

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenStore(tokenStore).authenticationManager(authenticationManager);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        //http configuration
    }

}

The TokenStore is just an instance of InMemoryTokenStore and AuthenticationManager is set up this way:

@Configuration
protected static class WebSecurity extends WebSecurityConfigurerAdapter {

    @Autowired
    protected UserDetailsManager userManager;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(preAuthenticationAuthenticationProvider())
                .userDetailsService(userManager).passwordEncoder(PASSWORD_ENCODER);
    }

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Bean
    protected AuthenticationProvider preAuthenticationAuthenticationProvider() {
        PreAuthenticatedAuthenticationProvider authenticationProvider =
                new PreAuthenticatedAuthenticationProvider();
        UserDetailsByNameServiceWrapper userDetailsWrapper = new UserDetailsByNameServiceWrapper(userManager);
        authenticationProvider.setPreAuthenticatedUserDetailsService(userDetailsWrapper);
        return authenticationProvider;
    }

}

What I was missing are AuthorizationServiceTokenServices and ResourceServerTokenServices . Both these interfaces are implmented by Spring's DefaultTokenServices .

@Bean
public DefaultTokenServices tokenServices() {
    DefaultTokenServices tokenServices = new DefaultTokenServices();
    tokenServices.setTokenStore(tokenStore());
    tokenServices.setAuthenticationManager(authenticationManager);
    return tokenServices;
}

In the authorization server configuration ( AuthorizationServiceConfigurerAdapter ), I have the following setup:

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints.tokenServices(tokenServices()).authenticationManager(authenticationManager);
}

In the resource server configuration ( ResourceServerConfigurerAdapter ):

@Autowired
private DefaultTokenServices tokenServices;

@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    resources.tokenServices(tokenServices);
}

With all these components, my app works without any PreAuthenticationAuthenticationProvider bean defined.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM