Skip to content

Commit 477a456

Browse files
committed
Disable device_code grant by default
Closes gh-17998
1 parent 4dfef14 commit 477a456

File tree

2 files changed

+68
-14
lines changed

2 files changed

+68
-14
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2AuthorizationServerConfigurer.java

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,16 @@ public OAuth2AuthorizationServerConfigurer tokenRevocationEndpoint(
255255
*/
256256
public OAuth2AuthorizationServerConfigurer deviceAuthorizationEndpoint(
257257
Customizer<OAuth2DeviceAuthorizationEndpointConfigurer> deviceAuthorizationEndpointCustomizer) {
258-
deviceAuthorizationEndpointCustomizer
259-
.customize(getConfigurer(OAuth2DeviceAuthorizationEndpointConfigurer.class));
258+
OAuth2DeviceAuthorizationEndpointConfigurer deviceAuthorizationEndpointConfigurer = getConfigurer(
259+
OAuth2DeviceAuthorizationEndpointConfigurer.class);
260+
if (deviceAuthorizationEndpointConfigurer == null) {
261+
addConfigurer(OAuth2DeviceAuthorizationEndpointConfigurer.class,
262+
new OAuth2DeviceAuthorizationEndpointConfigurer(this::postProcess));
263+
deviceAuthorizationEndpointConfigurer = getConfigurer(OAuth2DeviceAuthorizationEndpointConfigurer.class);
264+
deviceVerificationEndpoint((configurer) -> {
265+
}); // Ensure the Device Verification Endpoint is enabled
266+
}
267+
deviceAuthorizationEndpointCustomizer.customize(deviceAuthorizationEndpointConfigurer);
260268
return this;
261269
}
262270

@@ -268,7 +276,16 @@ public OAuth2AuthorizationServerConfigurer deviceAuthorizationEndpoint(
268276
*/
269277
public OAuth2AuthorizationServerConfigurer deviceVerificationEndpoint(
270278
Customizer<OAuth2DeviceVerificationEndpointConfigurer> deviceVerificationEndpointCustomizer) {
271-
deviceVerificationEndpointCustomizer.customize(getConfigurer(OAuth2DeviceVerificationEndpointConfigurer.class));
279+
OAuth2DeviceVerificationEndpointConfigurer deviceVerificationEndpointConfigurer = getConfigurer(
280+
OAuth2DeviceVerificationEndpointConfigurer.class);
281+
if (deviceVerificationEndpointConfigurer == null) {
282+
addConfigurer(OAuth2DeviceVerificationEndpointConfigurer.class,
283+
new OAuth2DeviceVerificationEndpointConfigurer(this::postProcess));
284+
deviceVerificationEndpointConfigurer = getConfigurer(OAuth2DeviceVerificationEndpointConfigurer.class);
285+
deviceAuthorizationEndpoint((configurer) -> {
286+
}); // Ensure the Device Authorization Endpoint is enabled
287+
}
288+
deviceVerificationEndpointCustomizer.customize(deviceVerificationEndpointConfigurer);
272289
return this;
273290
}
274291

@@ -386,9 +403,11 @@ public void init(HttpSecurity httpSecurity) {
386403
preferredMatchers.add(getRequestMatcher(OAuth2TokenEndpointConfigurer.class));
387404
preferredMatchers.add(getRequestMatcher(OAuth2TokenIntrospectionEndpointConfigurer.class));
388405
preferredMatchers.add(getRequestMatcher(OAuth2TokenRevocationEndpointConfigurer.class));
389-
preferredMatchers.add(getRequestMatcher(OAuth2DeviceAuthorizationEndpointConfigurer.class));
390-
RequestMatcher preferredMatcher = getRequestMatcher(
391-
OAuth2PushedAuthorizationRequestEndpointConfigurer.class);
406+
RequestMatcher preferredMatcher = getRequestMatcher(OAuth2DeviceAuthorizationEndpointConfigurer.class);
407+
if (preferredMatcher != null) {
408+
preferredMatchers.add(preferredMatcher);
409+
}
410+
preferredMatcher = getRequestMatcher(OAuth2PushedAuthorizationRequestEndpointConfigurer.class);
392411
if (preferredMatcher != null) {
393412
preferredMatchers.add(preferredMatcher);
394413
}
@@ -478,10 +497,6 @@ private Map<Class<? extends AbstractOAuth2Configurer>, AbstractOAuth2Configurer>
478497
new OAuth2TokenIntrospectionEndpointConfigurer(this::postProcess));
479498
configurers.put(OAuth2TokenRevocationEndpointConfigurer.class,
480499
new OAuth2TokenRevocationEndpointConfigurer(this::postProcess));
481-
configurers.put(OAuth2DeviceAuthorizationEndpointConfigurer.class,
482-
new OAuth2DeviceAuthorizationEndpointConfigurer(this::postProcess));
483-
configurers.put(OAuth2DeviceVerificationEndpointConfigurer.class,
484-
new OAuth2DeviceVerificationEndpointConfigurer(this::postProcess));
485500
return configurers;
486501
}
487502

config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/OAuth2DeviceCodeGrantTests.java

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
import org.springframework.beans.factory.annotation.Autowired;
3636
import org.springframework.context.annotation.Bean;
37-
import org.springframework.context.annotation.Import;
37+
import org.springframework.context.annotation.Configuration;
3838
import org.springframework.http.HttpHeaders;
3939
import org.springframework.http.HttpStatus;
4040
import org.springframework.http.MediaType;
@@ -47,8 +47,9 @@
4747
import org.springframework.mock.http.client.MockClientHttpResponse;
4848
import org.springframework.mock.web.MockHttpServletResponse;
4949
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
50+
import org.springframework.security.config.Customizer;
51+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5052
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
51-
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
5253
import org.springframework.security.config.test.SpringTestContext;
5354
import org.springframework.security.config.test.SpringTestContextExtension;
5455
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
@@ -82,6 +83,7 @@
8283
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
8384
import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients;
8485
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
86+
import org.springframework.security.web.SecurityFilterChain;
8587
import org.springframework.test.web.servlet.MockMvc;
8688
import org.springframework.test.web.servlet.MvcResult;
8789
import org.springframework.util.LinkedMultiValueMap;
@@ -645,9 +647,25 @@ private static Function<OAuth2Authorization.Token<? extends OAuth2Token>, Boolea
645647
}
646648

647649
@EnableWebSecurity
648-
@Import(OAuth2AuthorizationServerConfiguration.class)
650+
@Configuration(proxyBeanMethods = false)
649651
static class AuthorizationServerConfiguration {
650652

653+
// @formatter:off
654+
@Bean
655+
SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
656+
http
657+
.oauth2AuthorizationServer((authorizationServer) ->
658+
authorizationServer
659+
.deviceAuthorizationEndpoint(Customizer.withDefaults())
660+
.deviceVerificationEndpoint(Customizer.withDefaults())
661+
)
662+
.authorizeHttpRequests((authorize) ->
663+
authorize.anyRequest().authenticated()
664+
);
665+
return http.build();
666+
}
667+
// @formatter:on
668+
651669
@Bean
652670
RegisteredClientRepository registeredClientRepository(JdbcOperations jdbcOperations) {
653671
return new JdbcRegisteredClientRepository(jdbcOperations);
@@ -675,6 +693,11 @@ JWKSource<SecurityContext> jwkSource() {
675693
return jwkSource;
676694
}
677695

696+
@Bean
697+
AuthorizationServerSettings authorizationServerSettings() {
698+
return AuthorizationServerSettings.builder().build();
699+
}
700+
678701
@Bean
679702
PasswordEncoder passwordEncoder() {
680703
return NoOpPasswordEncoder.getInstance();
@@ -683,9 +706,25 @@ PasswordEncoder passwordEncoder() {
683706
}
684707

685708
@EnableWebSecurity
686-
@Import(OAuth2AuthorizationServerConfiguration.class)
709+
@Configuration(proxyBeanMethods = false)
687710
static class AuthorizationServerConfigurationWithMultipleIssuersAllowed extends AuthorizationServerConfiguration {
688711

712+
// @formatter:off
713+
@Bean
714+
SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
715+
http
716+
.oauth2AuthorizationServer((authorizationServer) ->
717+
authorizationServer
718+
.deviceAuthorizationEndpoint(Customizer.withDefaults())
719+
.deviceVerificationEndpoint(Customizer.withDefaults())
720+
)
721+
.authorizeHttpRequests((authorize) ->
722+
authorize.anyRequest().authenticated()
723+
);
724+
return http.build();
725+
}
726+
// @formatter:on
727+
689728
@Bean
690729
AuthorizationServerSettings authorizationServerSettings() {
691730
return AuthorizationServerSettings.builder().multipleIssuersAllowed(true).build();

0 commit comments

Comments
 (0)