diff --git a/.vscode/cspell.json b/.vscode/cspell.json index bd85726cce1c..1ce3f3ab3379 100644 --- a/.vscode/cspell.json +++ b/.vscode/cspell.json @@ -1245,6 +1245,7 @@ "words": [ "aadb", "AADB", + "AADSTS", "amqps", "Authoritys", "autoconfiguation", diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/CHANGELOG.md b/sdk/spring/spring-cloud-azure-autoconfigure/CHANGELOG.md index 24ab5d428261..aa281c5af28a 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/CHANGELOG.md +++ b/sdk/spring/spring-cloud-azure-autoconfigure/CHANGELOG.md @@ -8,6 +8,8 @@ ### Bugs Fixed +- Fixed OAuth2 JWT Bearer grant request parameter duplication issue where `grant_type` was being duplicated when using the on-behalf-of flow, causing `AADSTS70003: unsupported_grant_type` error. [#47657](https://github.com/Azure/azure-sdk-for-java/issues/47657) + ### Other Changes ## 7.0.0-beta.1 (2025-12-23) diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/aad/security/AadJwtBearerGrantRequestParametersConverter.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/aad/security/AadJwtBearerGrantRequestParametersConverter.java index 234e2c8f2a02..fc201915ddc4 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/aad/security/AadJwtBearerGrantRequestParametersConverter.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/main/java/com/azure/spring/cloud/autoconfigure/implementation/aad/security/AadJwtBearerGrantRequestParametersConverter.java @@ -4,12 +4,16 @@ package com.azure.spring.cloud.autoconfigure.implementation.aad.security; import org.springframework.core.convert.converter.Converter; -import org.springframework.security.oauth2.client.endpoint.DefaultOAuth2TokenRequestParametersConverter; import org.springframework.security.oauth2.client.endpoint.JwtBearerGrantRequest; +import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; /** * This is a special JWT Bearer flow implementation for Microsoft identify platform. + * This converter only adds the Azure-specific parameter "requested_token_use" with value "on_behalf_of". + * The standard OAuth2 parameters (grant_type, assertion, client_id, etc.) are added by Spring Security's + * DefaultOAuth2TokenRequestParametersConverter, which is automatically included when using + * RestClientJwtBearerTokenResponseClient. * * @since 7.0.0 * @see OAuth 2.0 On-Behalf-Of @@ -17,12 +21,9 @@ public class AadJwtBearerGrantRequestParametersConverter implements Converter> { - private final DefaultOAuth2TokenRequestParametersConverter delegate = - new DefaultOAuth2TokenRequestParametersConverter<>(); - @Override public MultiValueMap convert(JwtBearerGrantRequest jwtBearerGrantRequest) { - MultiValueMap parameters = delegate.convert(jwtBearerGrantRequest); + MultiValueMap parameters = new LinkedMultiValueMap<>(); parameters.add("requested_token_use", "on_behalf_of"); return parameters; } diff --git a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/aad/security/AadJwtBearerGrantRequestEntityConverterTests.java b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/aad/security/AadJwtBearerGrantRequestEntityConverterTests.java index bdeb4fe16707..53d5ed97b57f 100644 --- a/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/aad/security/AadJwtBearerGrantRequestEntityConverterTests.java +++ b/sdk/spring/spring-cloud-azure-autoconfigure/src/test/java/com/azure/spring/cloud/autoconfigure/implementation/aad/security/AadJwtBearerGrantRequestEntityConverterTests.java @@ -40,5 +40,11 @@ void requestedTokenUseParameter() { Assertions.assertNotNull(parameters); assertTrue(parameters.containsKey("requested_token_use")); assertEquals("on_behalf_of", parameters.getFirst("requested_token_use")); + // Verify that the converter does not add grant_type or other standard OAuth2 parameters + // to avoid duplication when composed with DefaultOAuth2TokenRequestParametersConverter + Assertions.assertFalse(parameters.containsKey("grant_type"), + "Converter should not add grant_type to avoid duplication"); + assertEquals(1, parameters.size(), + "Converter should only add the Azure-specific parameter"); } }