Disable device_code grant by default
CodeQL Advanced / codeql-analysis-call (push) Waiting to run Details
CI / Build (17, ubuntu-latest) (push) Waiting to run Details
CI / Build (17, windows-latest) (push) Waiting to run Details
CI / Deploy Artifacts (push) Blocked by required conditions Details
CI / Deploy Docs (push) Blocked by required conditions Details
CI / Deploy Schema (push) Blocked by required conditions Details
CI / Perform Release (push) Blocked by required conditions Details
CI / Send Notification (push) Blocked by required conditions Details
Deploy Docs / build (push) Waiting to run Details

Closes gh-17998
This commit is contained in:
Joe Grandja 2025-10-03 13:57:41 -04:00
parent 4dfef1483d
commit 477a456d6c
2 changed files with 68 additions and 14 deletions

View File

@ -255,8 +255,16 @@ public final class OAuth2AuthorizationServerConfigurer
*/
public OAuth2AuthorizationServerConfigurer deviceAuthorizationEndpoint(
Customizer<OAuth2DeviceAuthorizationEndpointConfigurer> deviceAuthorizationEndpointCustomizer) {
deviceAuthorizationEndpointCustomizer
.customize(getConfigurer(OAuth2DeviceAuthorizationEndpointConfigurer.class));
OAuth2DeviceAuthorizationEndpointConfigurer deviceAuthorizationEndpointConfigurer = getConfigurer(
OAuth2DeviceAuthorizationEndpointConfigurer.class);
if (deviceAuthorizationEndpointConfigurer == null) {
addConfigurer(OAuth2DeviceAuthorizationEndpointConfigurer.class,
new OAuth2DeviceAuthorizationEndpointConfigurer(this::postProcess));
deviceAuthorizationEndpointConfigurer = getConfigurer(OAuth2DeviceAuthorizationEndpointConfigurer.class);
deviceVerificationEndpoint((configurer) -> {
}); // Ensure the Device Verification Endpoint is enabled
}
deviceAuthorizationEndpointCustomizer.customize(deviceAuthorizationEndpointConfigurer);
return this;
}
@ -268,7 +276,16 @@ public final class OAuth2AuthorizationServerConfigurer
*/
public OAuth2AuthorizationServerConfigurer deviceVerificationEndpoint(
Customizer<OAuth2DeviceVerificationEndpointConfigurer> deviceVerificationEndpointCustomizer) {
deviceVerificationEndpointCustomizer.customize(getConfigurer(OAuth2DeviceVerificationEndpointConfigurer.class));
OAuth2DeviceVerificationEndpointConfigurer deviceVerificationEndpointConfigurer = getConfigurer(
OAuth2DeviceVerificationEndpointConfigurer.class);
if (deviceVerificationEndpointConfigurer == null) {
addConfigurer(OAuth2DeviceVerificationEndpointConfigurer.class,
new OAuth2DeviceVerificationEndpointConfigurer(this::postProcess));
deviceVerificationEndpointConfigurer = getConfigurer(OAuth2DeviceVerificationEndpointConfigurer.class);
deviceAuthorizationEndpoint((configurer) -> {
}); // Ensure the Device Authorization Endpoint is enabled
}
deviceVerificationEndpointCustomizer.customize(deviceVerificationEndpointConfigurer);
return this;
}
@ -386,9 +403,11 @@ public final class OAuth2AuthorizationServerConfigurer
preferredMatchers.add(getRequestMatcher(OAuth2TokenEndpointConfigurer.class));
preferredMatchers.add(getRequestMatcher(OAuth2TokenIntrospectionEndpointConfigurer.class));
preferredMatchers.add(getRequestMatcher(OAuth2TokenRevocationEndpointConfigurer.class));
preferredMatchers.add(getRequestMatcher(OAuth2DeviceAuthorizationEndpointConfigurer.class));
RequestMatcher preferredMatcher = getRequestMatcher(
OAuth2PushedAuthorizationRequestEndpointConfigurer.class);
RequestMatcher preferredMatcher = getRequestMatcher(OAuth2DeviceAuthorizationEndpointConfigurer.class);
if (preferredMatcher != null) {
preferredMatchers.add(preferredMatcher);
}
preferredMatcher = getRequestMatcher(OAuth2PushedAuthorizationRequestEndpointConfigurer.class);
if (preferredMatcher != null) {
preferredMatchers.add(preferredMatcher);
}
@ -478,10 +497,6 @@ public final class OAuth2AuthorizationServerConfigurer
new OAuth2TokenIntrospectionEndpointConfigurer(this::postProcess));
configurers.put(OAuth2TokenRevocationEndpointConfigurer.class,
new OAuth2TokenRevocationEndpointConfigurer(this::postProcess));
configurers.put(OAuth2DeviceAuthorizationEndpointConfigurer.class,
new OAuth2DeviceAuthorizationEndpointConfigurer(this::postProcess));
configurers.put(OAuth2DeviceVerificationEndpointConfigurer.class,
new OAuth2DeviceVerificationEndpointConfigurer(this::postProcess));
return configurers;
}

View File

@ -34,7 +34,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@ -47,8 +47,9 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.mock.http.client.MockClientHttpResponse;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
@ -82,6 +83,7 @@ import org.springframework.security.oauth2.server.authorization.client.Registere
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.util.LinkedMultiValueMap;
@ -645,9 +647,25 @@ public class OAuth2DeviceCodeGrantTests {
}
@EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class)
@Configuration(proxyBeanMethods = false)
static class AuthorizationServerConfiguration {
// @formatter:off
@Bean
SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
http
.oauth2AuthorizationServer((authorizationServer) ->
authorizationServer
.deviceAuthorizationEndpoint(Customizer.withDefaults())
.deviceVerificationEndpoint(Customizer.withDefaults())
)
.authorizeHttpRequests((authorize) ->
authorize.anyRequest().authenticated()
);
return http.build();
}
// @formatter:on
@Bean
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
return new JdbcRegisteredClientRepository(jdbcOperations);
@ -675,6 +693,11 @@ public class OAuth2DeviceCodeGrantTests {
return jwkSource;
}
@Bean
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().build();
}
@Bean
PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
@ -683,9 +706,25 @@ public class OAuth2DeviceCodeGrantTests {
}
@EnableWebSecurity
@Import(OAuth2AuthorizationServerConfiguration.class)
@Configuration(proxyBeanMethods = false)
static class AuthorizationServerConfigurationWithMultipleIssuersAllowed extends AuthorizationServerConfiguration {
// @formatter:off
@Bean
SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
http
.oauth2AuthorizationServer((authorizationServer) ->
authorizationServer
.deviceAuthorizationEndpoint(Customizer.withDefaults())
.deviceVerificationEndpoint(Customizer.withDefaults())
)
.authorizeHttpRequests((authorize) ->
authorize.anyRequest().authenticated()
);
return http.build();
}
// @formatter:on
@Bean
AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();