Open mraible opened 1 year ago
I was able to fix this by customizing the authorization request. It'd be nice if this were built-in for Auth0.
package com.example.apigateway;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizationRequestResolver;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.security.web.SecurityFilterChain;
import java.util.function.Consumer;
@Configuration
public class SecurityConfiguration {
@Value("${okta.oauth2.audience}")
private String audience;
private final ClientRegistrationRepository clientRegistrationRepository;
public SecurityConfiguration(ClientRegistrationRepository clientRegistrationRepository) {
this.clientRegistrationRepository = clientRegistrationRepository;
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2Login(oauth2 -> oauth2
.authorizationEndpoint(authorization -> authorization
.authorizationRequestResolver(
authorizationRequestResolver(this.clientRegistrationRepository)
)
)
);
return http.build();
}
private OAuth2AuthorizationRequestResolver authorizationRequestResolver(
ClientRegistrationRepository clientRegistrationRepository) {
DefaultOAuth2AuthorizationRequestResolver authorizationRequestResolver =
new DefaultOAuth2AuthorizationRequestResolver(
clientRegistrationRepository, "/oauth2/authorization");
authorizationRequestResolver.setAuthorizationRequestCustomizer(
authorizationRequestCustomizer());
return authorizationRequestResolver;
}
private Consumer<OAuth2AuthorizationRequest.Builder> authorizationRequestCustomizer() {
return customizer -> customizer
.additionalParameters(params -> params.put("audience", audience));
}
}
Here's the configuration that's needed when using Spring WebFlux:
package com.example.apigateway;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.server.DefaultServerOAuth2AuthorizationRequestResolver;
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizationRequestResolver;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.security.web.server.SecurityWebFilterChain;
import java.util.function.Consumer;
@Configuration
public class SecurityConfiguration {
@Value("${okta.oauth2.audience}")
private String audience;
private final ReactiveClientRegistrationRepository clientRegistrationRepository;
public SecurityConfiguration(ReactiveClientRegistrationRepository clientRegistrationRepository) {
this.clientRegistrationRepository = clientRegistrationRepository;
}
@Bean
public SecurityWebFilterChain filterChain(ServerHttpSecurity http) throws Exception {
http
.authorizeExchange(authz -> authz
.anyExchange().authenticated()
)
.oauth2Login(oauth2 -> oauth2
.authorizationRequestResolver(
authorizationRequestResolver(this.clientRegistrationRepository)
)
);
return http.build();
}
private ServerOAuth2AuthorizationRequestResolver authorizationRequestResolver(
ReactiveClientRegistrationRepository clientRegistrationRepository) {
DefaultServerOAuth2AuthorizationRequestResolver authorizationRequestResolver =
new DefaultServerOAuth2AuthorizationRequestResolver(
clientRegistrationRepository);
authorizationRequestResolver.setAuthorizationRequestCustomizer(
authorizationRequestCustomizer());
return authorizationRequestResolver;
}
private Consumer<OAuth2AuthorizationRequest.Builder> authorizationRequestCustomizer() {
return customizer -> customizer
.additionalParameters(params -> params.put("audience", audience));
}
}
I'm submitting a
Background info
If I use this starter in a Spring Boot 3.1.3 app, I don't get a JWT as an access token. I believe this is because it doesn't send the audience parameter to the
/authorize
endpoint. With Okta, I do get an access token as a JWT. Here's how I'm testing it:If you start an app with this configuration, log in, then go to
http://localhost:8080/print-token
, you'll see the access token in your console. Copy and paste it into jwt.io. It will work for Okta, but not for Auth0.Expected behavior
I thought by defining
OKTA_OAUTH2_AUDIENCE
as an environment variable, it'd be used for validation and fetching JWTs.Steps to reproduce
See above.
SDK Version
3.0.5