我有一个 Spring Boot 3 服务,它使用 Auth0/Okta 来保护其 API。用户获得令牌并可以调用我的端点。我在 application.yaml 中使用这些参数:
okta:
oauth2:
audience:
issuer:
我的服务还需要能够调用 Auth0,例如能够使用 OAuth2 令牌创建用户
Auth0 端的设置已正确,因为在使用为我的服务颁发的 clientId 和 clientSecret 检索令牌后,我可以使用 Postman 进行调用。
我认为使用 SDK 和启动器并将其嵌入到我的服务中会很简单,但我没有找到实现这一目标的方法:
并通过私钥:
我找不到任何关于如何使用 Oauth2 实现类似目标的资源。
当我“手动”尝试时,通过自己设置更多代码,我无法获得令牌,因为 Auth0 需要一个
audience
参数,而 Spring Security 不支持开箱即用的参数(https:// github.com/spring-projects/spring-security/issues/6569)
考虑到 Spring Boot 和 Auth0 的流行,我本以为这会很容易,但事实证明,我没有找到任何一个可以在 Spring Boot 3 / Spring Security 6 中或多或少开箱即用的示例..
最后,这些都是有用的资源:
我是否错过了文档中的任何内容,或者真的没有更好的方法使用 OAuth2 调用 Auth0 API 吗?
我刚刚完成了这个练习,所以请允许我提供帮助。
首先,我要说的是,我使用了okta SDK和Auth0.com,但没有得到很好的体验。
<dependency>
<groupId>com.okta</groupId>
<artifactId>okta-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
我还使用了 Okta 的 Auth0,因为它是一个免费的面向开发人员的平台。
我的项目使用了Spring安全依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
我的项目还做了用于登录的常规 Web 应用程序和用于 API 的资源服务器。由于您只对资源服务器感兴趣,我可以向您展示这一点。
将其添加到您的 application.yml 中。
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: ${auth0audience-issuer-uri}
audiences: ${auth0audience-audience}
client:
registration:
auth0:
client-id: ${auth0audience-client-id}
client-secret: ${auth0audience-client-secret}
provider: auth0
provider:
auth0:
issuer-uri: ${auth0audience-issuer-uri}
然后配置
SecurityFilterChain
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())).build();
}
}
正如您所发现的,困难实际上在于通过 WebClient 访问它。必须配置添加
audience
参数
@Configuration
public class WebClientConfiguration {
@Value("${spring.security.oauth2.resourceserver.jwt.audiences}")
private String audience;
@Bean
public WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
return WebClient.builder()
.apply(oauth2Client.oauth2Configuration())
.baseUrl("http://localhost:8080/")
.build();
}
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService authorizedClientService) {
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials((builder) ->
builder.accessTokenResponseClient(clientCredentialsAccessTokenResponseClient())
.build())
.build();
AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
private OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsAccessTokenResponseClient() {
DefaultClientCredentialsTokenResponseClient accessTokenResponseClient =
new DefaultClientCredentialsTokenResponseClient();
OAuth2ClientCredentialsGrantRequestEntityConverter requestEntityConverter =
new OAuth2ClientCredentialsGrantRequestEntityConverter();
requestEntityConverter.addParametersConverter(source -> CollectionUtils.toMultiValueMap(Collections.singletonMap("audience", Collections.singletonList(audience))));
accessTokenResponseClient.setRequestEntityConverter(requestEntityConverter);
return accessTokenResponseClient;
}
}
然后就可以使用了。
@SpringBootApplication
public class Auth0WebClientAudienceApplication implements ApplicationRunner {
public static void main(String[] args) {
SpringApplication.run(Auth0WebClientAudienceApplication.class, args);
}
@Autowired
WebClient webClient;
@Override
public void run(ApplicationArguments args) throws Exception {
List<String> r = webClient.get().uri("movies")
.attributes(clientRegistrationId("auth0"))
.retrieve()
.bodyToMono(new ParameterizedTypeReference<List<String>>() {
}).block();
System.out.println("movies = " + r);
}
}
仅供参考
@RestController
@RequestMapping
public class MovieApi {
@GetMapping("movies")
public List<String> getMovies() {
SecurityContext securityContext = SecurityContextHolder.getContext();
if (!(securityContext instanceof AnonymousAuthenticationToken)) {
return List.of("movie1", "movie2");
}
return Collections.emptyList();
}
}
Git 存储库位于 Auth0WebClientAudience。
Spring Security Framework 在 OAuth 2.0 Client 上有一些不充分的文档。