我正在尝试实现client_credentials grant以在我的spring Boot 资源服务器中获取token。我使用Auth 0作为授权服务器。他们似乎需要在请求主体中添加一个额外的参数,称为audience。
我已经尝试通过postman完成请求,并且成功了。我现在正在尝试在Spring中重现它。
curl -X POST \
https://XXX.auth0.com/oauth/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials&audience=https%3A%2F%2Fxxxxx.auth0.com%2Fapi%2Fv2%2F&client_id=SOME_CLIENT_ID&client_secret=SOME_CLIENT_SECRET'
字符串
我面临的问题是,我没有办法将缺少的受众参数添加到令牌请求中。
我在我的application.yml中定义了一个配置
client:
provider:
auth0:
issuer-uri: https://XXXX.auth0.com//
registration:
auth0-client:
provider: auth0
client-id: Client
client-secret: Secret
authorization_grant_type: client_credentials
auth0:
client-id: Client
client-secret: Secret
型
我有这样配置的Web客户端过滤器。
@Bean
WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations,
ServerOAuth2AuthorizedClientRepository authorizedClients) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2 = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrations, authorizedClients);
oauth2.setDefaultClientRegistrationId("auth0");
return WebClient.builder()
.filter(oauth2)
.build();
}
型
我注入示例,并试图做一个请求,以获得用户通过电子邮件
return this.webClient.get()
.uri(this.usersUrl + "/api/v2/users-by-email?email={email}", email)
.attributes(auth0ClientCredentials())
.retrieve()
.bodyToMono(User.class);
型
据我所知,过滤器拦截了这个userByEmail请求,在执行它之前,它试图执行/oauth/token请求以获取JWT承载令牌,它可以附加到第一个令牌并执行它。
有没有一种方法来添加一个参数到过滤器?它一直非常困难,通过它,并找出确切的参数被附加,因为它的React和我在这方面相当新。甚至一些指针,在哪里看会有帮助。
5条答案
按热度按时间ttisahbt1#
我遇到了同样的问题,访问令牌响应和请求不符合oAuth2标准。下面是我的代码(它在Kotlin中,但对于java开发人员来说也应该是可以理解的),用于spring Boot 版本
2.3.6.RELEASE
。Gradle依赖项:字符串
在添加它们之后,你必须首先创建你的自定义令牌请求/响应客户端,它将实现
ReactiveOAuth2AccessTokenResponseClient
接口:型
正如您在上面看到的,在这个类中,您可以根据您的特定需求调整令牌请求/响应处理。
注意事项:
getTokenResponse
方法中的authorizationGrantRequest
参数。Spring在这里传递来自应用程序属性的数据,因此在定义它们时遵循标准,例如,它们可能看起来像这样:型
最后一步是在oAuth2配置中使用
CustomTokenResponseClient
,它可能看起来像这样:型
b4qexyjb2#
现在,这是可能的,但不是优雅的。
请注意,您可以为
ServerOAuth2AuthorizedClientExchangeFilterFunction
提供自定义的ReactiveOAuth2AccessTokenResponseClient
。您可以通过复制
WebClientReactiveClientCredentialsTokenResponseClient
的内容来创建自己的实现,从而添加所需的任何其他参数。也就是说,如果有一个setter来使其更方便,那就更好了。
igetnqfo3#
下面是我在进一步调查后发现的。我的问题中描述的代码永远不会调用client_credentials并适合我的用例。我认为(不是100%确定)如果我试图在微服务架构中的多个服务中传播用户提交的令牌,它将在未来非常有用。像这样的动作链浮现在脑海中:
用户调用服务A ->服务A调用服务B ->服务B响应->服务A响应用户请求。
并使用相同的令牌开始与通过整个过程。
我的用例解决方案:
我所做的是在很大程度上基于原始类创建一个新的Filter类,并在执行请求之前执行一个步骤,检查是否存储了可用于Auth 0 Management API的JWT令牌。如果没有,我构建client_credentials grant请求并获取一个,然后把这个token作为一个bearer附加到初始请求上,然后执行那个请求。我还在-内存缓存机制,以便如果令牌有效,以后的任何其他请求都将使用它。
过滤器
字符串
代币存储
型
令牌存储接口
型
最后定义并使用这些bean。
型
此时令牌存储有一个小问题,因为client_credentials令牌请求将在同时到来的并行请求上执行多个,但我可以在可预见的未来接受这一点。
fhity93d4#
您的application.yml缺少一个变量:client-authentication-method:post
应该是这样的:
字符串
如果没有它,我总是得到“invalid_client”的响应。
在Spring罩2.7.2中进行测试
k2arahey5#
还有另一种方法可以解决这个问题。如果对
auth0.com
API的client_credentials令牌请求在请求主体中不包括audience
字段,那么auth0.com
将默认为https://jwtresourceapi
。因此,为了能够使用WebClient
,上面@DArkO提供的(令人惊叹的)解决方案,您可以在https://jwtresourceapi
的受众中使用auth0.com
创建所有API。我不知道你还需要什么,但我所做的只是在
auth0.com
中定义一个API,我可以有多个应用程序。只要应用程序在API的机器对机器应用程序中被授权,它就可以工作。请记住,
auth0.com
只是一个开发者的Playground,我不会用它来创建生产就绪的应用程序。PS>我还必须在配置文件中包含
authorization-grant-type: client_credentials
,尽管配置bean示例说我不需要它。也许我稍后会弄清楚,但现在这是有效的。