简体   繁体   English

在刷新令牌上未找到AuthenticationProvider-Spring OAuth2 Java配置

[英]No AuthenticationProvider found on refresh token - Spring OAuth2 java config

I have a Spring Boot project in which I've configured a Spring OAuth2 authentication process which partially works. 我有一个Spring Boot项目,在其中配置了部分起作用的Spring OAuth2身份验证过程。 I can authenticate OK but when I'm trying to get a refresh token I get an exception. 我可以验证OK,但是当我尝试获取刷新令牌时会出现异常。

OAuth configuration: OAuth配置:

@Configuration
public class OAuth2ServerConfiguration {

    private static final String RESOURCE_ID = "xxx";

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) {
            resources.resourceId(RESOURCE_ID);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
            .authorizeRequests()
            .antMatchers("/api/**").authenticated();
        }
    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

        @Value("${clientDetailsService.clientName}")
        private String clientName;

        @Value("${clientDetailsService.clientSecret}")
        private String clientSecret;

        @Autowired
        @Qualifier("authenticationManager")
        private AuthenticationManager authenticationManager;

        @Autowired
        private ClientDetailsService clientDetailsService;

        @Autowired
        @Qualifier("tokenServices")
        private AuthorizationServerTokenServices tokenServices;

        @Autowired
        @Qualifier("codeServices")
        private AuthorizationCodeServices codeServices;

        @Autowired
        @Qualifier("requestFactory")
        private OAuth2RequestFactory requestFactory;

        @Autowired
        @Qualifier("tokenGranter")
        private TokenGranter tokenGranter;

        private final TokenStore tokenStore = new InMemoryTokenStore();

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.setClientDetailsService(clientDetailsService);
            endpoints.tokenServices(tokenServices)
                        .tokenStore(tokenStore)
                        .authorizationCodeServices(codeServices)
                        .authenticationManager(authenticationManager)
                        .requestFactory(requestFactory)
                        .tokenGranter(tokenGranter);
        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.withClientDetails(clientDetailsService);
        }


        @Bean(name = "tokenGranter")
        @Primary
        public TokenGranter tokenGranter() {
            final List<TokenGranter> tokenGranters = new ArrayList<TokenGranter>();

            tokenGranters.add(new AuthorizationCodeTokenGranter(tokenServices, codeServices, clientDetailsService, requestFactory));
            tokenGranters.add(new RefreshTokenGranter(tokenServices, clientDetailsService, requestFactory));
            tokenGranters.add(new ImplicitTokenGranter(tokenServices, clientDetailsService, requestFactory));
            tokenGranters.add(new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, requestFactory));
            tokenGranters.add(new CustomTokenGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory));

            return new CompositeTokenGranter(tokenGranters);
        }

        @Bean
        @Primary
        public ClientDetailsService clientDetailsService(){
            final InMemoryClientDetailsServiceBuilder builder = new InMemoryClientDetailsServiceBuilder();
            builder.withClient(clientName)
                    .authorizedGrantTypes("password", "refresh_token")
                    .authorities("USER")
                    .scopes("read", "write")
                    .resourceIds(RESOURCE_ID)
                    .secret(clientSecret);

            try {
                return builder.build();
            } catch (final Exception e) {
                e.printStackTrace();
            }

            return null;

        }

        @Bean(name = "tokenServices")
        @Primary
        public AuthorizationServerTokenServices tokenServices() {
            final DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setSupportRefreshToken(true);
            tokenServices.setClientDetailsService(clientDetailsService);
            tokenServices.setTokenStore(tokenStore);
            tokenServices.setAuthenticationManager(authenticationManager);
            return tokenServices;
        }

        @Bean(name = "requestFactory")
        @Primary
        public OAuth2RequestFactory requestFactory() {
            return new DefaultOAuth2RequestFactory(clientDetailsService);
        }

        @Bean(name = "codeServices")
        @Primary
        public AuthorizationCodeServices authorizationCodeServices() {
            return new InMemoryAuthorizationCodeServices();
        }
    }

I also have some custom components defined, like a custom Token Granter, custom authentication provider etc. I'll post them if necessary. 我还定义了一些自定义组件,例如自定义令牌授予者,自定义身份验证提供程序等。如有必要,我将发布它们。

As I said, authentication flow works OK. 正如我所说,身份验证流程可以正常运行。 When I POST to /oauth/token I get a token and a refresh token, but when I then try to exchange my refresh token for a new token (by POSTing http://localhost:8080/oauth/token with grant_type=refresh_token and refresh_token=my refresh token) I get an exception: 当我发布到/ oauth / token时,我得到一个令牌和一个刷新令牌,但是当我尝试将我的刷新令牌交换为一个新令牌时(通过使用grant_type = refresh_token POST http:// localhost:8080 / oauth / token , refresh_token =我的刷新令牌)出现异常:

No AuthenticationProvider found for org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken 找不到org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken的AuthenticationProvider

Where do I set the authentication provider? 在哪里设置身份验证提供程序? How do I get Spring to use my custom authentication provider for refresh tokens also? 如何使Spring还将我的自定义身份验证提供程序也用于刷新令牌?

I fixed this by explicitly defining a PreAuthenticationProvider: 我通过显式定义PreAuthenticationProvider来解决此问题:

@Component("preAuthProvider")
public class CustomPreAuthProvider extends PreAuthenticatedAuthenticationProvider {

    @Autowired
    private AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> userService;

    public CustomPreAuthProvider(){
        super();
    }

    @PostConstruct
    public void init(){
        super.setPreAuthenticatedUserDetailsService(userService);
    }
}

and then a custom userservice: 然后是自定义用户服务:

@Service
public class CustomPreAuthUserDetailsService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {

    @Override
    public final UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken token) {
    ...    
    }
}

and adding this provider to the oauth2 config: 并将此提供程序添加到oauth2配置中:

@Autowired
private AuthenticationProvider authenticationProvider;

@Autowired
@Qualifier("preAuthProvider")
private AuthenticationProvider preAuthProvider;

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

I can not be disagree with Jesper's answer, but in my case, that same error has been fixed removing: 我不能不同意Jesper的回答,但就我而言,该错误已得到修复,已删除:

tokenServices.setAuthenticationManager(authenticationManager) 

from tokenService() 来自tokenService()

As an alternative way to Jesper's answer, if you want to reuse your current UserDetailsService for this purpose, you can just do it the same way as Spring does it with their DefaultTokenServices : 作为Jesper回答的一种替代方法,如果您想为此目的重用当前的UserDetailsService ,则可以使用与Spring对其DefaultTokenServices相同的方式进行操作:

@Bean
public CustomTokenServices tokenServices() {
    CustomTokenServices tokenServices = new CustomTokenServices();
    tokenServices.setTokenStore(tokenStore());
    tokenServices.setSupportRefreshToken(true);
    tokenServices.setReuseRefreshToken(false);
    tokenServices.setClientDetailsService(clientDetailsService);
    tokenServices.setAuthenticationManager(createPreAuthProvider());
    return tokenServices;
}

private ProviderManager createPreAuthProvider() {
    PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
    provider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper<>(userDetailsService));
    return new ProviderManager(Arrays.asList(provider));
}

UserDetailsService is autowired into this @Configuration class. UserDetailsService自动连接到此@Configuration类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 春季OAuth2刷新令牌 - Spring OAuth2 Refresh token 找不到UsernamePasswordAuthenticationToken的AuthenticationProvider - Spring-boot + Oauth2:Restful API - No AuthenticationProvider found for UsernamePasswordAuthenticationToken - Spring-boot + Oauth2: Restful API Spring OAuth2没有提供刷新令牌 - Spring OAuth2 not giving refresh token Gmail 在 Java 中带有 Oauth2,带有带有 AuthorizationCodeFlow 的刷新令牌 - Gmail with Oauth2 in Java with refresh token with AuthorizationCodeFlow Spring刷新访问令牌后刷新令牌以更改令牌 - Spring OAuth2 refresh token to change after refreshing access token Spring OAuth2安全性-客户端凭据-自定义AuthenticationProvider - Spring OAuth2 Security - Client Credentials - Custom AuthenticationProvider Spring Security-Oauth2将请求参数传递给AuthenticationProvider - Spring Security - Oauth2 Pass Request Paramerter to the AuthenticationProvider Spring 安全 OAuth2 刷新令牌 - IllegalStateException,需要 UserDetailsS​​ervice - Spring security OAuth2 Refresh Token - IllegalStateException, UserDetailsService is required 使用Spring Security OAuth2的刷新令牌为null - refresh token is null using Spring Security OAuth2 Spring 启动 - google oauth2,在数据库中存储刷新令牌 - Spring boot - google oauth2, store refresh token in database
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM