diff --git a/common/src/main/java/com/microsoft/identity/common/internal/broker/BrokerRequest.java b/common/src/main/java/com/microsoft/identity/common/internal/broker/BrokerRequest.java index 92bdb5cf90..f998c8d52e 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/broker/BrokerRequest.java +++ b/common/src/main/java/com/microsoft/identity/common/internal/broker/BrokerRequest.java @@ -63,6 +63,7 @@ private static final class SerializedNames { final static String LOCAL_ACCOUNT_ID = "local_account_id"; final static String USERNAME = "username"; final static String EXTRA_QUERY_STRING_PARAMETER = "extra_query_param"; + final static String EXTRA_TOKEN_BODY_PARAMETER = "extra_token_body_param"; final static String CORRELATION_ID = "correlation_id"; final static String PROMPT = "prompt"; final static String CLAIMS = "claims"; @@ -140,6 +141,13 @@ private static final class SerializedNames { @SerializedName(SerializedNames.EXTRA_QUERY_STRING_PARAMETER) private String mExtraQueryStringParameter; + /** + * Extra token body parameters for the request. + */ + @Nullable + @SerializedName(SerializedNames.EXTRA_TOKEN_BODY_PARAMETER) + private String mExtraTokenBodyParameter; + /** * Extra options flags for the request. */ diff --git a/common/src/main/java/com/microsoft/identity/common/internal/request/MsalBrokerRequestAdapter.java b/common/src/main/java/com/microsoft/identity/common/internal/request/MsalBrokerRequestAdapter.java index a3d50dd02f..ed63df5e4c 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/request/MsalBrokerRequestAdapter.java +++ b/common/src/main/java/com/microsoft/identity/common/internal/request/MsalBrokerRequestAdapter.java @@ -60,6 +60,7 @@ import com.microsoft.identity.common.java.commands.parameters.DeviceCodeFlowCommandParameters; import com.microsoft.identity.common.java.commands.parameters.GenerateShrCommandParameters; import com.microsoft.identity.common.java.commands.parameters.GetAadDeviceIdCommandParameters; +import com.microsoft.identity.common.java.commands.parameters.IHasExtraTokenBodyParameters; import com.microsoft.identity.common.java.commands.parameters.InteractiveTokenCommandParameters; import com.microsoft.identity.common.java.commands.parameters.RemoveAccountCommandParameters; import com.microsoft.identity.common.java.commands.parameters.ResourceAccountCommandParameters; @@ -80,6 +81,8 @@ import com.microsoft.identity.common.logging.Logger; import java.io.IOException; +import java.util.List; +import java.util.Map; public class MsalBrokerRequestAdapter implements IBrokerRequestAdapter { @@ -95,6 +98,8 @@ public BrokerRequest brokerRequestFromAcquireTokenParameters(@NonNull final Inte : null; final String extraOptions = parameters.getExtraOptions() != null ? QueryParamsAdapter._toJson(parameters.getExtraOptions()) : null; + final String extraTokenBodyParameters = parameters.getExtraTokenBodyParameters() != null ? + QueryParamsAdapter._toJson(parameters.getExtraTokenBodyParameters()) : null; final BrokerRequest.BrokerRequestBuilder brokerRequestBuilder = BrokerRequest.builder() .authority(parameters.getAuthority().getAuthorityURL().toString()) @@ -106,6 +111,7 @@ public BrokerRequest brokerRequestFromAcquireTokenParameters(@NonNull final Inte .userName(parameters.getLoginHint()) .extraQueryStringParameter(extraQueryStringParameter) .extraOptions(extraOptions) + .extraTokenBodyParameter(extraTokenBodyParameters) .prompt((OpenIdConnectPromptParameter.UNSET.name().equals(parameters.getPrompt().name())) ? null : parameters.getPrompt().name()) .claims(parameters.getClaimsRequestJson()) .forceRefresh(parameters.isForceRefresh()) @@ -178,7 +184,7 @@ public BrokerRequest brokerRequestFromSilentOperationParameters(@NonNull final S final String extraOptions = parameters.getExtraOptions() != null ? QueryParamsAdapter._toJson(parameters.getExtraOptions()) : null; - final BrokerRequest brokerRequest = BrokerRequest.builder() + final BrokerRequest.BrokerRequestBuilder brokerRequestBuilder = BrokerRequest.builder() .authority(parameters.getAuthority().getAuthorityURL().toString()) .scope(TextUtils.join(" ", parameters.getScopes())) .redirect(parameters.getRedirectUri()) @@ -205,10 +211,14 @@ public BrokerRequest brokerRequestFromSilentOperationParameters(@NonNull final S .spanId(SpanExtension.current().getSpanContext().getSpanId()) .traceFlags(SpanExtension.current().getSpanContext().getTraceFlags().asByte()) .build() - ) - .build(); - - return brokerRequest; + ); + if (parameters instanceof IHasExtraTokenBodyParameters) { + final List> extraTokenBodyParams = ((IHasExtraTokenBodyParameters) parameters).getExtraTokenBodyParameters(); + final String extraTokenBodyParameters = extraTokenBodyParams != null ? + QueryParamsAdapter._toJson(extraTokenBodyParams) : null; + brokerRequestBuilder.extraTokenBodyParameter(extraTokenBodyParameters); + } + return brokerRequestBuilder.build(); } public @NonNull Bundle getRequestBundleForSsoToken(final @NonNull AcquirePrtSsoTokenCommandParameters parameters, diff --git a/common/src/test/java/com/microsoft/identity/common/internal/request/MsalBrokerRequestAdapterTests.java b/common/src/test/java/com/microsoft/identity/common/internal/request/MsalBrokerRequestAdapterTests.java index e9c658b2a1..ff647a92cf 100644 --- a/common/src/test/java/com/microsoft/identity/common/internal/request/MsalBrokerRequestAdapterTests.java +++ b/common/src/test/java/com/microsoft/identity/common/internal/request/MsalBrokerRequestAdapterTests.java @@ -47,17 +47,24 @@ import com.microsoft.identity.common.java.commands.parameters.GetAadDeviceIdCommandParameters; import com.microsoft.identity.common.java.commands.parameters.InteractiveTokenCommandParameters; import com.microsoft.identity.common.java.commands.parameters.ResourceAccountCommandParameters; +import com.microsoft.identity.common.java.exception.ClientException; import com.microsoft.identity.common.java.interfaces.IPlatformComponents; import com.microsoft.identity.common.java.providers.oauth2.OpenIdConnectPromptParameter; import com.microsoft.identity.common.java.request.SdkType; import com.microsoft.identity.common.java.ui.BrowserDescriptor; +import com.microsoft.identity.common.java.util.QueryParamsAdapter; import com.microsoft.identity.common.java.util.StringUtil; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Set; import lombok.SneakyThrows; @@ -173,12 +180,12 @@ public void test_getRequestBundleForAcquireTokenInteractive_forAccountTransfer() } @Test - public void test_BrokerRequestFromAcquireTokenParameters() { + public void test_BrokerRequestFromAcquireTokenParameters() throws ClientException{ test_BrokerRequestFromAcquireTokenParametersInternal(false); } @Test - public void test_BrokerRequestFromAcquireTokenParameters_SuppressBrokerPicker() { + public void test_BrokerRequestFromAcquireTokenParameters_SuppressBrokerPicker() throws ClientException{ test_BrokerRequestFromAcquireTokenParametersInternal(true); } @@ -282,12 +289,15 @@ public void testGetRequestBundleForProvisionResourceAccount() { assertEquals(mockRedirectUri, brokerRequest.getRedirect()); } - private void test_BrokerRequestFromAcquireTokenParametersInternal(final boolean suppressBrokerAccountPicker) { + private void test_BrokerRequestFromAcquireTokenParametersInternal(final boolean suppressBrokerAccountPicker) throws ClientException { final Set scopes = new HashSet<>(); scopes.add("user.read"); final IPlatformComponents components = MockPlatformComponentsFactory.getNonFunctionalBuilder().build(); + final List> extraTokenBodyParams = new ArrayList<>(); + extraTokenBodyParams.add(new AbstractMap.SimpleEntry<>("key1", "value1")); + final InteractiveTokenCommandParameters params = InteractiveTokenCommandParameters.builder() .platformComponents(components) .correlationId("987d8962-3f4d-4054-a852-ac0c4b6a602e") @@ -309,6 +319,7 @@ private void test_BrokerRequestFromAcquireTokenParametersInternal(final boolean .preferredBrowser(new BrowserDescriptor("chrome", "signature", null, null)) .claimsRequestJson("claims_request") .brokerBrowserSupportEnabled(true) + .extraTokenBodyParameters(extraTokenBodyParams) .build(); final MsalBrokerRequestAdapter msalBrokerRequestAdapter = new MsalBrokerRequestAdapter(); final BrokerRequest brokerRequest = msalBrokerRequestAdapter.brokerRequestFromAcquireTokenParameters(params); @@ -328,6 +339,7 @@ private void test_BrokerRequestFromAcquireTokenParametersInternal(final boolean assertEquals(params.getPrompt().name(), brokerRequest.getPrompt()); assertEquals(params.isSuppressBrokerAccountPicker(), brokerRequest.isSuppressAccountPicker()); assertNull(brokerRequest.getSignInWithGoogleCredential()); + assertEquals(params.getExtraTokenBodyParameters(), QueryParamsAdapter._fromJson(brokerRequest.getExtraTokenBodyParameter())); } /** diff --git a/common4j/src/main/com/microsoft/identity/common/java/commands/parameters/BrokerSilentTokenCommandParameters.java b/common4j/src/main/com/microsoft/identity/common/java/commands/parameters/BrokerSilentTokenCommandParameters.java index 3bd82e5e0a..3578dec877 100644 --- a/common4j/src/main/com/microsoft/identity/common/java/commands/parameters/BrokerSilentTokenCommandParameters.java +++ b/common4j/src/main/com/microsoft/identity/common/java/commands/parameters/BrokerSilentTokenCommandParameters.java @@ -29,6 +29,10 @@ import com.microsoft.identity.common.java.request.BrokerRequestType; import com.microsoft.identity.common.java.util.StringUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.experimental.SuperBuilder; @@ -36,7 +40,9 @@ @Getter @SuperBuilder(toBuilder = true) @EqualsAndHashCode(callSuper = true) -public class BrokerSilentTokenCommandParameters extends SilentTokenCommandParameters implements IBrokerTokenCommandParameters { +public class BrokerSilentTokenCommandParameters + extends SilentTokenCommandParameters + implements IHasExtraTokenBodyParameters, IBrokerTokenCommandParameters { @Expose private final int callerUid; @@ -55,6 +61,9 @@ public class BrokerSilentTokenCommandParameters extends SilentTokenCommandParame @Expose private final String negotiatedBrokerProtocolVersion; + // Only put in the token request body + private final List> extraTokenBodyParameters; + // If this flag is true, we will send the x-ms-PKeyAuth Header to the token endpoint. // Note: this flag is transferred to a MicrosoftTokenRequest in BaseController. @Expose @@ -74,6 +83,11 @@ public boolean isRequestForResourceAccount() { return false; } + @Override + public List> getExtraTokenBodyParameters() { + return this.extraTokenBodyParameters == null ? null : new ArrayList<>(this.extraTokenBodyParameters); + } + @Override public void validate() throws ArgumentException { if (callerUid == 0) { diff --git a/common4j/src/main/com/microsoft/identity/common/java/commands/parameters/IHasExtraTokenBodyParameters.java b/common4j/src/main/com/microsoft/identity/common/java/commands/parameters/IHasExtraTokenBodyParameters.java new file mode 100644 index 0000000000..da2cd047c0 --- /dev/null +++ b/common4j/src/main/com/microsoft/identity/common/java/commands/parameters/IHasExtraTokenBodyParameters.java @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. +// All rights reserved. +// +// This code is licensed under the MIT License. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +package com.microsoft.identity.common.java.commands.parameters; + +import java.util.List; +import java.util.Map; + +/** + * Interface indicating that a class carries a set of string/string parameters that are intended + * to be merged into the OAuth2 token request body only. + */ +public interface IHasExtraTokenBodyParameters { + + /** + * Get the {@link List} of pairs of String, String parameters. + * + * @return a list of pairs of String, String parameters - this may be null. + * {@link UnsupportedOperationException} or result in undefined behavior. + */ + List> getExtraTokenBodyParameters(); +} diff --git a/common4j/src/main/com/microsoft/identity/common/java/commands/parameters/InteractiveTokenCommandParameters.java b/common4j/src/main/com/microsoft/identity/common/java/commands/parameters/InteractiveTokenCommandParameters.java index edb30c5da0..a78da8adfe 100644 --- a/common4j/src/main/com/microsoft/identity/common/java/commands/parameters/InteractiveTokenCommandParameters.java +++ b/common4j/src/main/com/microsoft/identity/common/java/commands/parameters/InteractiveTokenCommandParameters.java @@ -41,7 +41,8 @@ @Getter @EqualsAndHashCode(callSuper = true) @SuperBuilder(toBuilder = true) -public class InteractiveTokenCommandParameters extends TokenCommandParameters { +public class InteractiveTokenCommandParameters extends TokenCommandParameters + implements IHasExtraTokenBodyParameters { private final transient List browserSafeList; @@ -70,6 +71,9 @@ public class InteractiveTokenCommandParameters extends TokenCommandParameters { private final List> extraQueryStringParameters; + // Only put in the token request body + private final List> extraTokenBodyParameters; + @Expose() private final List extraScopesToConsent; @@ -91,6 +95,11 @@ public List> getExtraQueryStringParameters() { return this.extraQueryStringParameters == null ? null : new ArrayList<>(this.extraQueryStringParameters); } + @Override + public List> getExtraTokenBodyParameters() { + return this.extraTokenBodyParameters == null ? null : new ArrayList<>(this.extraTokenBodyParameters); + } + public List getExtraScopesToConsent() { return this.extraScopesToConsent == null ? null : new ArrayList<>(this.extraScopesToConsent); }