Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vscode/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -1245,6 +1245,7 @@
"words": [
"aadb",
"AADB",
"AADSTS",
"amqps",
"Authoritys",
"autoconfiguation",
Expand Down
2 changes: 2 additions & 0 deletions sdk/spring/spring-cloud-azure-autoconfigure/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,26 @@
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 <a href="https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow">OAuth 2.0 On-Behalf-Of</a>
*/
public class AadJwtBearerGrantRequestParametersConverter
implements Converter<JwtBearerGrantRequest, MultiValueMap<String, String>> {

private final DefaultOAuth2TokenRequestParametersConverter<JwtBearerGrantRequest> delegate =
new DefaultOAuth2TokenRequestParametersConverter<>();

@Override
public MultiValueMap<String, String> convert(JwtBearerGrantRequest jwtBearerGrantRequest) {
MultiValueMap<String, String> parameters = delegate.convert(jwtBearerGrantRequest);
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.add("requested_token_use", "on_behalf_of");
return parameters;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}
Loading