spring webclient OAuth2未授权客户端\u凭据

spring webclient OAuth2未授权客户端\u凭据,spring,spring-security,oauth-2.0,webclient,Spring,Spring Security,Oauth 2.0,Webclient,我正在开发一个Spring引导应用程序,目前正在尝试调用一个使用OAuth2的服务 应用程序是一个后端,正在调用另一个后端 我已经配置了一个webclient bean来处理获取令牌的调用,并在令牌过期时再次检索令牌。但我有一个例外: 2021-04-16 11:09:04.569 ERROR 7744 --- [nio-8080-exec-2] OAuth2AuthorizationRequestRedirectFilter : Authorization Request failed: ja

我正在开发一个Spring引导应用程序,目前正在尝试调用一个使用OAuth2的服务

应用程序是一个后端,正在调用另一个后端

我已经配置了一个webclient bean来处理获取令牌的调用,并在令牌过期时再次检索令牌。但我有一个例外:

2021-04-16 11:09:04.569 ERROR 7744 --- [nio-8080-exec-2] OAuth2AuthorizationRequestRedirectFilter : Authorization Request failed: java.lang.IllegalArgumentException: Invalid Authorization Grant Type (client_credentials) for Client Registration with Id: drs

java.lang.IllegalArgumentException: Invalid Authorization Grant Type (client_credentials) for Client Registration with Id: drs
    at org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizationRequestResolver.resolve(DefaultOAuth2AuthorizationRequestResolver.java:142)
    at org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizationRequestResolver.resolve(DefaultOAuth2AuthorizationRequestResolver.java:89)
    at org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.doFilterInternal(OAuth2AuthorizationRequestRedirectFilter.java:149)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:117)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:108)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1591)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
我的bean配置:

@Configuration
public class OAuthEndpointClientConfiguration {

    @Bean
    public ReactiveClientRegistrationRepository clientRegistrations(
            @Value("${spring.security.oauth2.client.provider.drs.token-uri}") String tokenUri,
            @Value("${spring.security.oauth2.client.registration.drs.client-id}") String clientId,
            @Value("${spring.security.oauth2.client.registration.drs.client-secret}") String clientSecret,
            @Value("${spring.security.oauth2.client.registration.drs.scope}") String scope,
            @Value("${spring.security.oauth2.client.registration.drs.authorization-grant-type}") AuthorizationGrantType grantType,
            @Value("${spring.security.oauth2.client.registration.drs.client-authentication-method}") ClientAuthenticationMethod authenticationMethod
    ) {
        ClientRegistration clientRegistration = ClientRegistration
                .withRegistrationId("service")
                .tokenUri(tokenUri)
                .clientId(clientId)
                .clientSecret(clientSecret)
                .authorizationGrantType(grantType)
                .scope(scope)
                .build();
        return new InMemoryReactiveClientRegistrationRepository(clientRegistration);
    }

    @Bean
    public WebClient oAuthWebClient(ReactiveClientRegistrationRepository clientRegistrations) {
        ServerOAuth2AuthorizedClientExchangeFilterFunction oAuth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
                clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
        oAuth.setDefaultClientRegistrationId("service");
        return WebClient.builder().filter(oAuth).build();
    }

}
我必须配置一个ReactiveClientRegistrationRepository,因为在自动连线中找不到它。 我必须使用的授权类型是client_凭证,但如上所述,它引发了一个异常。 查看异常来自的类(默认类)时,我们可以看到,如果授权类型不同于AuthorizationGrantType.AUTHORIZATION\u代码或AuthorizationGrantType.IMPLICIT,则会引发异常:

package org.springframework.security.oauth2.client.web;

public final class DefaultOAuth2AuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver {
    private static final String REGISTRATION_ID_URI_VARIABLE_NAME = "registrationId";
    private static final char PATH_DELIMITER = '/';
    private final ClientRegistrationRepository clientRegistrationRepository;
    private final AntPathRequestMatcher authorizationRequestMatcher;
    private final StringKeyGenerator stateGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder());
    private final StringKeyGenerator secureKeyGenerator = new Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(), 96);

    public DefaultOAuth2AuthorizationRequestResolver(ClientRegistrationRepository clientRegistrationRepository, String authorizationRequestBaseUri) {
        Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
        Assert.hasText(authorizationRequestBaseUri, "authorizationRequestBaseUri cannot be empty");
        this.clientRegistrationRepository = clientRegistrationRepository;
        this.authorizationRequestMatcher = new AntPathRequestMatcher(authorizationRequestBaseUri + "/{" + "registrationId" + "}");
    }

(......)
    
    private OAuth2AuthorizationRequest resolve(HttpServletRequest request, String registrationId, String redirectUriAction) {
        if (registrationId == null) {
            return null;
        } else {
            ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId(registrationId);
            if (clientRegistration == null) {
                throw new IllegalArgumentException("Invalid Client Registration with Id: " + registrationId);
            } else {
                Map<String, Object> attributes = new HashMap();
                attributes.put("registration_id", clientRegistration.getRegistrationId());
                Builder builder;
                if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())) {
                    builder = OAuth2AuthorizationRequest.authorizationCode();
                    Map<String, Object> additionalParameters = new HashMap();
                    if (!CollectionUtils.isEmpty(clientRegistration.getScopes()) && clientRegistration.getScopes().contains("openid")) {
                        this.addNonceParameters(attributes, additionalParameters);
                    }

                    if (ClientAuthenticationMethod.NONE.equals(clientRegistration.getClientAuthenticationMethod())) {
                        this.addPkceParameters(attributes, additionalParameters);
                    }

                    builder.additionalParameters(additionalParameters);
                } else {
                    if (!AuthorizationGrantType.IMPLICIT.equals(clientRegistration.getAuthorizationGrantType())) {
                        throw new IllegalArgumentException("Invalid Authorization Grant Type (" + clientRegistration.getAuthorizationGrantType().getValue() + ") for Client Registration with Id: " + clientRegistration.getRegistrationId());
                    }

                    builder = OAuth2AuthorizationRequest.implicit();
                }

                String redirectUriStr = expandRedirectUri(request, clientRegistration, redirectUriAction);
                OAuth2AuthorizationRequest authorizationRequest = builder.clientId(clientRegistration.getClientId()).authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()).redirectUri(redirectUriStr).scopes(clientRegistration.getScopes()).state(this.stateGenerator.generateKey()).attributes(attributes).build();
                return authorizationRequest;
            }
        }
    }
    
}
package org.springframework.security.oauth2.client.web;
公共最终类DefaultOAuth2AuthorizationRequestResolver实现OAuth2AuthorizationRequestResolver{
私有静态最终字符串注册\u ID\u URI\u变量\u NAME=“registrationId”;
私有静态最终字符路径_分隔符='/';
专用最终ClientRegistrationRepository ClientRegistrationRepository;
私有最终AntPathRequestMatcher授权RequestMatcher;
私有最终StringKeyGenerator stateGenerator=new Base64StringKeyGenerator(Base64.getUrlEncoder());
私有最终StringKeyGenerator secureKeyGenerator=新的Base64StringKeyGenerator(Base64.getUrlEncoder().withoutPadding(),96);
public DefaultOAuth2AuthorizationRequestResolver(ClientRegistrationRepository ClientRegistrationRepository,String authorizationRequestBaseUri){
Assert.notNull(clientRegistrationRepository,“clientRegistrationRepository不能为null”);
Assert.hasText(authorizationRequestBaseUri,“authorizationRequestBaseUri不能为空”);
this.clientRegistrationRepository=clientRegistrationRepository;
this.authorizationRequestMatcher=新的AntPathRequestMatcher(authorizationRequestBaseUri++“/{“+”注册ID“+”});
}
(......)
私有OAuth2AuthorizationRequest解析(HttpServletRequest请求、字符串注册ID、字符串重定向操作){
如果(注册ID==null){
返回null;
}否则{
ClientRegistration ClientRegistration=this.clientRegistrationRepository.FindByrRegistrationID(registrationId);
if(clientRegistration==null){
抛出新的IllegalArgumentException(“Id为:+registrationId的客户端注册无效”);
}否则{
Map attributes=newhashmap();
attributes.put(“registration_id”,clientRegistration.getRegistrationId());
建筑商;
if(AuthorizationGrantType.AUTHORIZATION_CODE.equals(clientRegistration.getAuthorizationGrantType())){
builder=OAuth2AuthorizationRequest.authorizationCode();
Map additionalParameters=new HashMap();
如果(!CollectionUtils.isEmpty(clientRegistration.getScopes())和&clientRegistration.getScopes()包含(“openid”)){
this.addnonseparameters(属性、附加参数);
}
if(ClientAuthenticationMethod.NONE.equals(clientRegistration.getClientAuthenticationMethod())){
this.addPkceParameters(属性、附加参数);
}
生成器。附加参数(附加参数);
}否则{
如果(!AuthorizationGrantType.IMPLICIT.equals(clientRegistration.getAuthorizationGrantType())){
为Id为“+clientRegistration.getRegistrationId()”的客户端注册抛出新的IllegalArgumentException(“无效的授权授予类型”(+clientRegistration.getAuthorizationGrantType().getValue()+”);
}
builder=OAuth2AuthorizationRequest.implicit();
}
字符串redirectUriStr=expandRedirectUri(请求、clientRegistration、RedirectUrAction);
OAuth2AuthorizationRequest authorizationRequest=builder.clientId(clientRegistration.getClientId()).authorizationUri(clientRegistration.getProviderDetails().getAuthorizationUri()).redirectUri(redirectUriStr).scopes(clientRegistration.getScopes()).state(this.stateGenerateKey()).attributes(attributes).build();
返回授权请求;
}
}
}
}
所以我有点卡住了,因为我必须使用client_凭据作为授权类型,但是这个类禁止我这样做。我猜我缺少一个配置,但我找不到什么。我找到的每个解决方案都只是解释了web客户端bean的部分,并说它应该可以工作

我甚至不确定它是否应该通过分解器?我很难理解解析程序的用途,它似乎是在应用程序本身想要使用oAuth时使用的。但这不是我的情况,我只想调用另一个使用oAuth的应用程序。我有点迷路了