Allow custom token settings for OAuth 2.0 dynamic client registration
Closes gh-18870
This commit is contained in:
+62
@@ -411,6 +411,30 @@ public class OAuth2ClientRegistrationTests {
|
|||||||
.isCloseTo(expectedSecretExpiryDate, allowedDelta);
|
.isCloseTo(expectedSecretExpiryDate, allowedDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void requestWhenClientRegistersWithCustomTokenSettingsThenSavedToRegisteredClient() throws Exception {
|
||||||
|
this.spring.register(CustomTokenSettingsConfiguration.class).autowire();
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
OAuth2ClientRegistration clientRegistration = OAuth2ClientRegistration.builder()
|
||||||
|
.clientName("client-name")
|
||||||
|
.redirectUri("https://client.example.com")
|
||||||
|
.grantType(AuthorizationGrantType.AUTHORIZATION_CODE.getValue())
|
||||||
|
.grantType(AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
|
||||||
|
.scope("scope1")
|
||||||
|
.scope("scope2")
|
||||||
|
.build();
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
OAuth2ClientRegistration clientRegistrationResponse = registerClient(clientRegistration);
|
||||||
|
|
||||||
|
RegisteredClient registeredClient = this.registeredClientRepository
|
||||||
|
.findByClientId(clientRegistrationResponse.getClientId());
|
||||||
|
|
||||||
|
assertThat(registeredClient).isNotNull();
|
||||||
|
assertThat(registeredClient.getTokenSettings().getAccessTokenTimeToLive()).isEqualTo(Duration.ofMinutes(60));
|
||||||
|
}
|
||||||
|
|
||||||
private OAuth2ClientRegistration registerClient(OAuth2ClientRegistration clientRegistration) throws Exception {
|
private OAuth2ClientRegistration registerClient(OAuth2ClientRegistration clientRegistration) throws Exception {
|
||||||
// ***** (1) Obtain the "initial" access token used for registering the client
|
// ***** (1) Obtain the "initial" access token used for registering the client
|
||||||
|
|
||||||
@@ -600,6 +624,44 @@ public class OAuth2ClientRegistrationTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EnableWebSecurity
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
static class CustomTokenSettingsConfiguration extends AuthorizationServerConfiguration {
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
@Bean
|
||||||
|
@Override
|
||||||
|
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
|
||||||
|
http
|
||||||
|
.oauth2AuthorizationServer((authorizationServer) ->
|
||||||
|
authorizationServer
|
||||||
|
.clientRegistrationEndpoint((clientRegistration) ->
|
||||||
|
clientRegistration
|
||||||
|
.authenticationProviders(configureClientRegistrationConverters())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.authorizeHttpRequests((authorize) ->
|
||||||
|
authorize.anyRequest().authenticated()
|
||||||
|
);
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
private Consumer<List<AuthenticationProvider>> configureClientRegistrationConverters() {
|
||||||
|
// @formatter:off
|
||||||
|
return (authenticationProviders) ->
|
||||||
|
authenticationProviders.forEach((authenticationProvider) -> {
|
||||||
|
if (authenticationProvider instanceof OAuth2ClientRegistrationAuthenticationProvider provider) {
|
||||||
|
OAuth2ClientRegistrationRegisteredClientConverter clientRegistrationRegisteredClientConverter = new OAuth2ClientRegistrationRegisteredClientConverter();
|
||||||
|
clientRegistrationRegisteredClientConverter.setTokenSettingsCustomizer((tokenSettings) -> tokenSettings.accessTokenTimeToLive(Duration.ofMinutes(60)));
|
||||||
|
provider.setRegisteredClientConverter(clientRegistrationRegisteredClientConverter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// @formatter:on
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
static class OpenClientRegistrationConfiguration extends AuthorizationServerConfiguration {
|
static class OpenClientRegistrationConfiguration extends AuthorizationServerConfiguration {
|
||||||
|
|||||||
+24
@@ -19,6 +19,7 @@ package org.springframework.security.oauth2.server.authorization.converter;
|
|||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.security.crypto.keygen.Base64StringKeyGenerator;
|
import org.springframework.security.crypto.keygen.Base64StringKeyGenerator;
|
||||||
@@ -29,6 +30,8 @@ import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResp
|
|||||||
import org.springframework.security.oauth2.server.authorization.OAuth2ClientRegistration;
|
import org.springframework.security.oauth2.server.authorization.OAuth2ClientRegistration;
|
||||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||||
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
|
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
|
||||||
|
import org.springframework.security.oauth2.server.authorization.settings.TokenSettings;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,6 +50,9 @@ public final class OAuth2ClientRegistrationRegisteredClientConverter
|
|||||||
private static final StringKeyGenerator CLIENT_SECRET_GENERATOR = new Base64StringKeyGenerator(
|
private static final StringKeyGenerator CLIENT_SECRET_GENERATOR = new Base64StringKeyGenerator(
|
||||||
Base64.getUrlEncoder().withoutPadding(), 48);
|
Base64.getUrlEncoder().withoutPadding(), 48);
|
||||||
|
|
||||||
|
private Consumer<TokenSettings.Builder> tokenSettingsCustomizer = (tokenSettings) -> {
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RegisteredClient convert(OAuth2ClientRegistration clientRegistration) {
|
public RegisteredClient convert(OAuth2ClientRegistration clientRegistration) {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
@@ -103,8 +109,26 @@ public final class OAuth2ClientRegistrationRegisteredClientConverter
|
|||||||
builder
|
builder
|
||||||
.clientSettings(clientSettingsBuilder.build());
|
.clientSettings(clientSettingsBuilder.build());
|
||||||
|
|
||||||
|
TokenSettings.Builder tokenSettingsBuilder = TokenSettings.builder();
|
||||||
|
this.tokenSettingsCustomizer.accept(tokenSettingsBuilder);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.tokenSettings(tokenSettingsBuilder.build());
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@code Consumer} providing access to the {@link TokenSettings.Builder}
|
||||||
|
* allowing the ability to customize the token configuration settings.
|
||||||
|
* @param tokenSettingsCustomizer the {@code Consumer} providing access to the
|
||||||
|
* {@link TokenSettings.Builder}
|
||||||
|
* @since 7.1
|
||||||
|
*/
|
||||||
|
public void setTokenSettingsCustomizer(Consumer<TokenSettings.Builder> tokenSettingsCustomizer) {
|
||||||
|
Assert.notNull(tokenSettingsCustomizer, "tokenSettingsCustomizer cannot be null");
|
||||||
|
this.tokenSettingsCustomizer = tokenSettingsCustomizer;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user