diff --git a/changelog.txt b/changelog.txt index 7d3dd5b54a..ea5020844b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,6 @@ vNext ---------- +- [MAJOR] Pass google id token to broker for enabling Sign in with Google (#2573) - [MINOR] Organize browser selection classes and change signature for get AuthorizationStrategy (#2564) - [MINOR] Add support for OneBox Environment (#2559) - [MINOR] Add support for claims requests for native authentication (#2572) diff --git a/common/src/main/java/com/microsoft/identity/common/adal/internal/AuthenticationConstants.java b/common/src/main/java/com/microsoft/identity/common/adal/internal/AuthenticationConstants.java index baabc607ce..a329df1c97 100644 --- a/common/src/main/java/com/microsoft/identity/common/adal/internal/AuthenticationConstants.java +++ b/common/src/main/java/com/microsoft/identity/common/adal/internal/AuthenticationConstants.java @@ -605,7 +605,7 @@ public static final class Broker { * * @see Android Auth Broker Protocol Versions */ - public static final String LATEST_MSAL_TO_BROKER_PROTOCOL_VERSION_CODE = "16.0"; + public static final String LATEST_MSAL_TO_BROKER_PROTOCOL_VERSION_CODE = "17.0"; /** * The maximum msal-to-broker protocol version known by clients such as MSAL Android. 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 071e7f04de..976598167a 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 @@ -26,6 +26,7 @@ import androidx.annotation.Nullable; import com.google.gson.annotations.SerializedName; +import com.microsoft.identity.common.internal.msafederation.google.SignInWithGoogleCredential; import com.microsoft.identity.common.java.authscheme.AbstractAuthenticationScheme; import com.microsoft.identity.common.java.opentelemetry.SerializableSpanContext; import com.microsoft.identity.common.java.providers.oauth2.OpenIdConnectPromptParameter; @@ -79,6 +80,7 @@ private static final class SerializedNames { final static String PREFERRED_AUTH_METHOD = "preferred_auth_method"; final static String ACCOUNT_TRANSFER_TOKEN = "account_transfer_token"; final static String SUPPRESS_ACCOUNT_PICKER = "suppress_account_picker"; + final static String SIGN_IN_WITH_GOOGLE_CREDENTIAL = "sign_in_with_google_credential"; } /** @@ -266,4 +268,8 @@ private static final class SerializedNames { */ @SerializedName(SerializedNames.SUPPRESS_ACCOUNT_PICKER) private boolean mSuppressAccountPicker; + + @Nullable + @SerializedName(SerializedNames.SIGN_IN_WITH_GOOGLE_CREDENTIAL) + private SignInWithGoogleCredential mSignInWithGoogleCredential; } diff --git a/common/src/main/java/com/microsoft/identity/common/internal/commands/parameters/AndroidActivityInteractiveTokenCommandParameters.java b/common/src/main/java/com/microsoft/identity/common/internal/commands/parameters/AndroidInteractiveTokenCommandParameters.java similarity index 87% rename from common/src/main/java/com/microsoft/identity/common/internal/commands/parameters/AndroidActivityInteractiveTokenCommandParameters.java rename to common/src/main/java/com/microsoft/identity/common/internal/commands/parameters/AndroidInteractiveTokenCommandParameters.java index 3a9a8408a7..18f207fa8b 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/commands/parameters/AndroidActivityInteractiveTokenCommandParameters.java +++ b/common/src/main/java/com/microsoft/identity/common/internal/commands/parameters/AndroidInteractiveTokenCommandParameters.java @@ -25,6 +25,7 @@ import android.app.Activity; import com.microsoft.identity.common.internal.controllers.BrokerMsalController; +import com.microsoft.identity.common.internal.msafederation.google.SignInWithGoogleCredential; import com.microsoft.identity.common.java.commands.parameters.InteractiveTokenCommandParameters; import lombok.EqualsAndHashCode; @@ -39,6 +40,8 @@ @Getter @SuperBuilder(toBuilder = true) @EqualsAndHashCode(callSuper = true) -public class AndroidActivityInteractiveTokenCommandParameters extends InteractiveTokenCommandParameters { +public class AndroidInteractiveTokenCommandParameters extends InteractiveTokenCommandParameters { private transient final Activity activity; + + private final SignInWithGoogleCredential signInWithGoogleCredential; } diff --git a/common/src/main/java/com/microsoft/identity/common/internal/controllers/BrokerMsalController.java b/common/src/main/java/com/microsoft/identity/common/internal/controllers/BrokerMsalController.java index 4871cde50d..a7839a2b97 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/controllers/BrokerMsalController.java +++ b/common/src/main/java/com/microsoft/identity/common/internal/controllers/BrokerMsalController.java @@ -67,7 +67,7 @@ import com.microsoft.identity.common.internal.cache.ClientActiveBrokerCache; import com.microsoft.identity.common.internal.cache.HelloCache; import com.microsoft.identity.common.internal.cache.HelloCacheResult; -import com.microsoft.identity.common.internal.commands.parameters.AndroidActivityInteractiveTokenCommandParameters; +import com.microsoft.identity.common.internal.commands.parameters.AndroidInteractiveTokenCommandParameters; import com.microsoft.identity.common.internal.request.MsalBrokerRequestAdapter; import com.microsoft.identity.common.internal.result.MsalBrokerResultAdapter; import com.microsoft.identity.common.internal.telemetry.Telemetry; @@ -358,8 +358,8 @@ public AcquireTokenResult acquireToken(final @NonNull InteractiveTokenCommandPar final Intent interactiveRequestIntent = getBrokerAuthorizationIntent(parameters); Activity activity = null; - if (parameters instanceof AndroidActivityInteractiveTokenCommandParameters) { - activity = ((AndroidActivityInteractiveTokenCommandParameters) parameters).getActivity(); + if (parameters instanceof AndroidInteractiveTokenCommandParameters) { + activity = ((AndroidInteractiveTokenCommandParameters) parameters).getActivity(); } //Pass this intent to the BrokerActivity which will be used to start this activity diff --git a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/IFederatedCredentialCallback.kt b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/IMsaFederatedCredentialCallback.kt similarity index 95% rename from common/src/main/java/com/microsoft/identity/common/internal/msafederation/IFederatedCredentialCallback.kt rename to common/src/main/java/com/microsoft/identity/common/internal/msafederation/IMsaFederatedCredentialCallback.kt index caad790d83..e7e3ee81ed 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/IFederatedCredentialCallback.kt +++ b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/IMsaFederatedCredentialCallback.kt @@ -26,7 +26,7 @@ package com.microsoft.identity.common.internal.msafederation * Interface for Federated Credential Callback. Helps calling sign methods * async from java. */ -interface IFederatedCredentialCallback { +interface IMsaFederatedCredentialCallback { /** * Called when the sign in is successful. */ diff --git a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/IFederatedSignInProvider.kt b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/IMsaFederatedSignInProvider.kt similarity index 92% rename from common/src/main/java/com/microsoft/identity/common/internal/msafederation/IFederatedSignInProvider.kt rename to common/src/main/java/com/microsoft/identity/common/internal/msafederation/IMsaFederatedSignInProvider.kt index 4d8cae35c1..5476b2fca3 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/IFederatedSignInProvider.kt +++ b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/IMsaFederatedSignInProvider.kt @@ -25,7 +25,7 @@ package com.microsoft.identity.common.internal.msafederation /** * Internal interface for Federated Sign In Providers. */ -internal interface IFederatedSignInProvider { - suspend fun signIn(): Result +internal interface IMsaFederatedSignInProvider { + suspend fun signIn(): Result suspend fun signOut() } diff --git a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/FederatedCredential.kt b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederatedCredential.kt similarity index 87% rename from common/src/main/java/com/microsoft/identity/common/internal/msafederation/FederatedCredential.kt rename to common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederatedCredential.kt index d05c01d162..d177e6ee81 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/FederatedCredential.kt +++ b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederatedCredential.kt @@ -22,8 +22,11 @@ // THE SOFTWARE. package com.microsoft.identity.common.internal.msafederation +import com.google.gson.annotations.SerializedName +import java.util.AbstractMap + /** * Represents credential artifact as result of successful sign in into a federated sign in provider * (Google/Apple). It can contain id token and/or auth code. See implementations for more details. */ -abstract class FederatedCredential(val federatedSignInProviderName: FederatedSignInProviderName) +abstract class MsaFederatedCredential(@SerializedName("signInProviderName") val signInProviderName: MsaFederatedSignInProviderName) diff --git a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/FederatedSignInParameters.kt b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederatedSignInParameters.kt similarity index 92% rename from common/src/main/java/com/microsoft/identity/common/internal/msafederation/FederatedSignInParameters.kt rename to common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederatedSignInParameters.kt index 8a3f63fb71..17380a7ac1 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/FederatedSignInParameters.kt +++ b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederatedSignInParameters.kt @@ -25,6 +25,6 @@ package com.microsoft.identity.common.internal.msafederation /** * Parameters for Federated Sign In. e.g. SignInWithGoogleParameters for Google. */ -abstract class FederatedSignInParameters { - abstract val providerName: FederatedSignInProviderName +abstract class MsaFederatedSignInParameters { + abstract val providerName: MsaFederatedSignInProviderName } diff --git a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/FederatedSignInProviderFactory.kt b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederatedSignInProviderFactory.kt similarity index 85% rename from common/src/main/java/com/microsoft/identity/common/internal/msafederation/FederatedSignInProviderFactory.kt rename to common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederatedSignInProviderFactory.kt index 5f3a6a78a6..7252841c90 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/FederatedSignInProviderFactory.kt +++ b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederatedSignInProviderFactory.kt @@ -29,14 +29,14 @@ import com.microsoft.identity.common.internal.msafederation.google.SignInWithGoo * Factory class to get the Federated Sign In Provider based on provider type in parameters * Currently only Google is supported. */ -internal object FederatedSignInProviderFactory { +internal object MsaFederatedSignInProviderFactory { /** * Get the Federated Sign In Provider based on provider type in parameters. */ - fun getProvider(parameters: FederatedSignInParameters): IFederatedSignInProvider { + fun getProvider(parameters: MsaFederatedSignInParameters): IMsaFederatedSignInProvider { return when (parameters.providerName) { - FederatedSignInProviderName.GOOGLE -> GoogleSignInProvider.create(parameters as SignInWithGoogleParameters, MsaFederationConstants.GOOGLE_MSA_WEB_CLIENT_ID) + MsaFederatedSignInProviderName.GOOGLE -> GoogleSignInProvider.create(parameters as SignInWithGoogleParameters, MsaFederationConstants.GOOGLE_MSA_WEB_CLIENT_ID) else -> { throw IllegalArgumentException("Unsupported provider type") diff --git a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/FederatedSignInProviderName.kt b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederatedSignInProviderName.kt similarity index 95% rename from common/src/main/java/com/microsoft/identity/common/internal/msafederation/FederatedSignInProviderName.kt rename to common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederatedSignInProviderName.kt index c700c3bf6b..c96a539e8a 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/FederatedSignInProviderName.kt +++ b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederatedSignInProviderName.kt @@ -26,7 +26,7 @@ package com.microsoft.identity.common.internal.msafederation * Enum class for Federated Sign In Provider Name like Google, Apple * Currently only Google is supported. */ -enum class FederatedSignInProviderName(private val idProviderName: String) { +enum class MsaFederatedSignInProviderName(private val idProviderName: String) { GOOGLE("google.com"), APPLE("apple.com"); // would be used later diff --git a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederationExtensions.kt b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederationExtensions.kt new file mode 100644 index 0000000000..622815ab4d --- /dev/null +++ b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/MsaFederationExtensions.kt @@ -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. +@file:JvmName("MsaFederationExtensions") +package com.microsoft.identity.common.internal.msafederation + +import com.microsoft.identity.common.internal.msafederation.google.SignInWithGoogleCredential +import java.util.AbstractMap + +/** + * Helper/Extension method to create header that can be used in MSA authorization + */ +fun SignInWithGoogleCredential.getIdProviderHeadersForAuthorization(): Map { + return mapOf(MsaFederationConstants.MSA_ID_TOKEN_HEADER_KEY to this.idToken) +} + +/** + * Helper/Extension method to create query parameter that can be used in MSA authorization + */ +fun SignInWithGoogleCredential.getIdProviderExtraQueryParamForAuthorization(): Map.Entry { + return AbstractMap.SimpleEntry(MsaFederationConstants.MSA_ID_PROVIDER_EXTRA_QUERY_PARAM_KEY, signInProviderName.getIdProviderName()) +} diff --git a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/GoogleSignInProvider.kt b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/GoogleSignInProvider.kt index 653c655b7a..dcb20eb66c 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/GoogleSignInProvider.kt +++ b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/GoogleSignInProvider.kt @@ -32,7 +32,7 @@ import com.google.android.libraries.identity.googleid.GetGoogleIdOption import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential import com.google.android.libraries.identity.googleid.GoogleIdTokenParsingException -import com.microsoft.identity.common.internal.msafederation.IFederatedSignInProvider +import com.microsoft.identity.common.internal.msafederation.IMsaFederatedSignInProvider import com.microsoft.identity.common.java.base64.Base64Util import com.microsoft.identity.common.java.exception.ClientException import com.microsoft.identity.common.logging.Logger @@ -48,7 +48,7 @@ import java.security.SecureRandom internal class GoogleSignInProvider(private val credentialManager: CredentialManager, private val parameters: SignInWithGoogleParameters, private val webClientId: String -) : IFederatedSignInProvider { +) : IMsaFederatedSignInProvider { companion object { private const val TAG = "GoogleSignInProvider" diff --git a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/ISignInWithGoogleCredentialCallback.kt b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/ISignInWithGoogleCredentialCallback.kt index 5867d07175..8c1dc03043 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/ISignInWithGoogleCredentialCallback.kt +++ b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/ISignInWithGoogleCredentialCallback.kt @@ -22,13 +22,13 @@ // THE SOFTWARE. package com.microsoft.identity.common.internal.msafederation.google -import com.microsoft.identity.common.internal.msafederation.IFederatedCredentialCallback +import com.microsoft.identity.common.internal.msafederation.IMsaFederatedCredentialCallback /** * Interface for Federated Credential Callback. Helps calling sign methods * async from java. */ interface ISignInWithGoogleCredentialCallback : - IFederatedCredentialCallback { + IMsaFederatedCredentialCallback { override fun onSuccess(credential: SignInWithGoogleCredential) } diff --git a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleApi.kt b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleApi.kt index fe1ff47be5..7aa8947162 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleApi.kt +++ b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleApi.kt @@ -23,7 +23,7 @@ package com.microsoft.identity.common.internal.msafederation.google import android.app.Activity -import com.microsoft.identity.common.internal.msafederation.FederatedSignInProviderFactory +import com.microsoft.identity.common.internal.msafederation.MsaFederatedSignInProviderFactory import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -34,7 +34,7 @@ import kotlinx.coroutines.withContext * Entry point for signing in with Google into MSA. */ class SignInWithGoogleApi internal constructor( - private val federatedSignInProviderFactory: FederatedSignInProviderFactory){ + private val federatedSignInProviderFactory: MsaFederatedSignInProviderFactory){ companion object { private const val TAG = "SignInWithGoogleApi" @@ -45,9 +45,14 @@ class SignInWithGoogleApi internal constructor( @JvmStatic fun getInstance(): SignInWithGoogleApi { return instance ?: synchronized(this) { - instance ?: SignInWithGoogleApi(FederatedSignInProviderFactory).also { instance = it } + instance ?: SignInWithGoogleApi(MsaFederatedSignInProviderFactory).also { instance = it } } } + + @JvmStatic + fun setInstance(api: SignInWithGoogleApi) { + instance = api + } } /** diff --git a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleCredential.kt b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleCredential.kt index 4cdd9d0086..efc9bb1266 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleCredential.kt +++ b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleCredential.kt @@ -22,21 +22,16 @@ // THE SOFTWARE. package com.microsoft.identity.common.internal.msafederation.google -import com.microsoft.identity.common.internal.msafederation.MsaFederationConstants.MSA_ID_TOKEN_HEADER_KEY -import com.microsoft.identity.common.internal.msafederation.FederatedCredential -import com.microsoft.identity.common.internal.msafederation.FederatedSignInProviderName +import com.google.gson.annotations.SerializedName +import com.microsoft.identity.common.internal.msafederation.MsaFederatedCredential +import com.microsoft.identity.common.internal.msafederation.MsaFederatedSignInProviderName +import java.io.Serializable /** * Represents credential artifact as result of successful sign in with google * It can contain id token. */ -data class SignInWithGoogleCredential internal constructor(internal val idToken: String) : FederatedCredential(FederatedSignInProviderName.GOOGLE) { - - /** - * Helper method to create header that can be used in MSA - * authorization. (Move to better place.) - */ - fun asHeaders(): Map { - return mapOf(MSA_ID_TOKEN_HEADER_KEY to idToken) - } +data class SignInWithGoogleCredential internal constructor( + @SerializedName("idToken") internal val idToken: String) : MsaFederatedCredential(MsaFederatedSignInProviderName.GOOGLE), Serializable { } + diff --git a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleParameters.kt b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleParameters.kt index 3355b5bff4..84db89567c 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleParameters.kt +++ b/common/src/main/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleParameters.kt @@ -23,8 +23,8 @@ package com.microsoft.identity.common.internal.msafederation.google import android.app.Activity -import com.microsoft.identity.common.internal.msafederation.FederatedSignInParameters -import com.microsoft.identity.common.internal.msafederation.FederatedSignInProviderName +import com.microsoft.identity.common.internal.msafederation.MsaFederatedSignInParameters +import com.microsoft.identity.common.internal.msafederation.MsaFederatedSignInProviderName /** * SignInWithGoogleParameters holds the parameters required for signing in with Google. @@ -34,7 +34,7 @@ import com.microsoft.identity.common.internal.msafederation.FederatedSignInProvi */ data class SignInWithGoogleParameters( internal val activity: Activity -) : FederatedSignInParameters() { +) : MsaFederatedSignInParameters() { /** * Secondary constructor to initialize the parameters with an option to use a bottom sheet UI. @@ -54,6 +54,6 @@ data class SignInWithGoogleParameters( /** * The provider type for the federated sign-in, which is Google in this case. */ - override val providerName: FederatedSignInProviderName - get() = FederatedSignInProviderName.GOOGLE + override val providerName: MsaFederatedSignInProviderName + get() = MsaFederatedSignInProviderName.GOOGLE } diff --git a/common/src/main/java/com/microsoft/identity/common/internal/providers/oauth2/AuthorizationActivityFactory.java b/common/src/main/java/com/microsoft/identity/common/internal/providers/oauth2/AuthorizationActivityFactory.java index 397513d88c..ee05ddb997 100644 --- a/common/src/main/java/com/microsoft/identity/common/internal/providers/oauth2/AuthorizationActivityFactory.java +++ b/common/src/main/java/com/microsoft/identity/common/internal/providers/oauth2/AuthorizationActivityFactory.java @@ -41,8 +41,9 @@ import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; -import com.microsoft.identity.common.internal.msafederation.FederatedSignInProviderName; +import com.microsoft.identity.common.internal.msafederation.MsaFederatedSignInProviderName; import com.microsoft.identity.common.internal.msafederation.MsaFederationConstants; +import com.microsoft.identity.common.internal.msafederation.MsaFederationExtensions; import com.microsoft.identity.common.internal.msafederation.google.SignInWithGoogleCredential; import com.microsoft.identity.common.internal.msafederation.google.SignInWithGoogleParameters; import com.microsoft.identity.common.internal.msafederation.google.SignInWithGoogleApi; @@ -60,6 +61,7 @@ import java.net.URISyntaxException; import java.util.HashMap; +import java.util.Map; /** * Constructs intents and/or fragments for interactive requests based on library configuration and current request. @@ -281,13 +283,14 @@ public static Intent getAuthorizationActivityIntent(final Context context, ) throws ClientException { // add header final HashMap requestHeadersWithGoogleAuthCredential = requestHeaders == null? new HashMap<>() : new HashMap<>(requestHeaders); - requestHeadersWithGoogleAuthCredential.putAll(signInWithGoogleCredential.asHeaders()); + requestHeadersWithGoogleAuthCredential.putAll(MsaFederationExtensions.getIdProviderHeadersForAuthorization(signInWithGoogleCredential)); // add id provider query parameter - String requestUrlWithIdProvider = null; + String requestUrlWithIdProvider; try { final CommonURIBuilder uriBuilder = new CommonURIBuilder(requestUrl); - uriBuilder.addParameterIfAbsent(MsaFederationConstants.MSA_ID_PROVIDER_EXTRA_QUERY_PARAM_KEY, FederatedSignInProviderName.GOOGLE.getIdProviderName()); + final Map.Entry extraQueryParamForAuthorization = MsaFederationExtensions.getIdProviderExtraQueryParamForAuthorization(signInWithGoogleCredential); + uriBuilder.addParameterIfAbsent(extraQueryParamForAuthorization.getKey(), extraQueryParamForAuthorization.getValue()); requestUrlWithIdProvider = uriBuilder.build().toString(); } catch (final URISyntaxException e) { throw new ClientException(ClientException.MALFORMED_URL, "Failed to add id provider query parameter to request URL", e); 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 0b94400a1d..aa03a76d9d 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 @@ -49,6 +49,7 @@ import com.microsoft.identity.common.adal.internal.AuthenticationConstants; import com.microsoft.identity.common.internal.broker.BrokerRequest; +import com.microsoft.identity.common.internal.commands.parameters.AndroidInteractiveTokenCommandParameters; import com.microsoft.identity.common.java.commands.parameters.AcquirePrtSsoTokenCommandParameters; import com.microsoft.identity.common.java.commands.parameters.DeviceCodeFlowCommandParameters; import com.microsoft.identity.common.java.commands.parameters.GenerateShrCommandParameters; @@ -92,7 +93,7 @@ public BrokerRequest brokerRequestFromAcquireTokenParameters(@NonNull final Inte 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()) @@ -127,10 +128,14 @@ public BrokerRequest brokerRequestFromAcquireTokenParameters(@NonNull final Inte .preferredBrowser(parameters.getPreferredBrowser()) .preferredAuthMethod(parameters.getPreferredAuthMethod()) .accountTransferToken(parameters.getAccountTransferToken()) - .suppressAccountPicker(parameters.isSuppressBrokerAccountPicker()) - .build(); + .suppressAccountPicker(parameters.isSuppressBrokerAccountPicker()); - return brokerRequest; + if (parameters instanceof AndroidInteractiveTokenCommandParameters) { + final AndroidInteractiveTokenCommandParameters androidInteractiveTokenCommandParameters = (AndroidInteractiveTokenCommandParameters) parameters; + brokerRequestBuilder.signInWithGoogleCredential(androidInteractiveTokenCommandParameters.getSignInWithGoogleCredential()); + } + + return brokerRequestBuilder.build(); } @Override diff --git a/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/MockGoogleSignInProvider.kt b/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/MockGoogleSignInProvider.kt index 3b8553e8d0..9e587333ff 100644 --- a/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/MockGoogleSignInProvider.kt +++ b/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/MockGoogleSignInProvider.kt @@ -22,9 +22,9 @@ // THE SOFTWARE. package com.microsoft.identity.common.internal.msafederation.google -import com.microsoft.identity.common.internal.msafederation.IFederatedSignInProvider +import com.microsoft.identity.common.internal.msafederation.IMsaFederatedSignInProvider -class MockGoogleSignInProvider : IFederatedSignInProvider { +class MockGoogleSignInProvider : IMsaFederatedSignInProvider { companion object { private const val MOCK_ID_TOKEN = "mockIdToken" } diff --git a/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleApiTest.kt b/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleApiTest.kt index 1d09296662..b5ff18a731 100644 --- a/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleApiTest.kt +++ b/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleApiTest.kt @@ -23,7 +23,7 @@ package com.microsoft.identity.common.internal.msafederation.google import android.app.Activity -import com.microsoft.identity.common.internal.msafederation.FederatedSignInProviderFactory +import com.microsoft.identity.common.internal.msafederation.MsaFederatedSignInProviderFactory import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.runBlocking @@ -40,7 +40,7 @@ import java.util.concurrent.CountDownLatch */ @RunWith(RobolectricTestRunner::class) class SignInWithGoogleApiTest { - private lateinit var mockFederatedSignInProviderFactory: FederatedSignInProviderFactory + private lateinit var mockFederatedSignInProviderFactory: MsaFederatedSignInProviderFactory private lateinit var mockGoogleSignInProvider: MockGoogleSignInProvider private lateinit var signInWithGoogleApi: SignInWithGoogleApi private lateinit var mockActivity: Activity diff --git a/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleCredentialTest.kt b/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleCredentialTest.kt index 3f7a5715eb..6d579a9c31 100644 --- a/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleCredentialTest.kt +++ b/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleCredentialTest.kt @@ -23,11 +23,14 @@ package com.microsoft.identity.common.internal.msafederation.google import com.microsoft.identity.common.internal.msafederation.MsaFederationConstants -import com.microsoft.identity.common.internal.msafederation.FederatedSignInProviderName +import com.microsoft.identity.common.internal.msafederation.MsaFederatedSignInProviderName import org.junit.Assert.assertEquals import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 +import com.google.gson.Gson +import com.microsoft.identity.common.internal.msafederation.getIdProviderExtraQueryParamForAuthorization +import com.microsoft.identity.common.internal.msafederation.getIdProviderHeadersForAuthorization /** * Tests for [SignInWithGoogleCredential]. @@ -39,11 +42,21 @@ class SignInWithGoogleCredentialTest { fun testSignInWithGoogleCredential() { val testIdToken = "test-id-token" val credential = SignInWithGoogleCredential(testIdToken) - assertEquals(FederatedSignInProviderName.GOOGLE, credential.federatedSignInProviderName) + assertEquals(MsaFederatedSignInProviderName.GOOGLE, credential.signInProviderName) assertEquals(testIdToken, credential.idToken) - val headers = credential.asHeaders(); + val headers = credential.getIdProviderHeadersForAuthorization(); assertEquals(1, headers.size) assertEquals(testIdToken, headers[MsaFederationConstants.MSA_ID_TOKEN_HEADER_KEY]) + + val idProviderExtraQueryParam = credential.getIdProviderExtraQueryParamForAuthorization() + assertEquals(MsaFederationConstants.MSA_ID_PROVIDER_EXTRA_QUERY_PARAM_KEY, idProviderExtraQueryParam.key) + assertEquals(MsaFederatedSignInProviderName.GOOGLE.getIdProviderName(), idProviderExtraQueryParam.value) + + // serialize and deserialize credential using gson + val gson = Gson() + val json = gson.toJson(credential) + val deserializedCredential = gson.fromJson(json, SignInWithGoogleCredential::class.java) + assertEquals(credential, deserializedCredential) } } diff --git a/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleParametersTest.kt b/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleParametersTest.kt index 127a42a2bd..d6b8c8032a 100644 --- a/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleParametersTest.kt +++ b/common/src/test/java/com/microsoft/identity/common/internal/msafederation/google/SignInWithGoogleParametersTest.kt @@ -23,7 +23,7 @@ package com.microsoft.identity.common.internal.msafederation.google import android.app.Activity -import com.microsoft.identity.common.internal.msafederation.FederatedSignInProviderName +import com.microsoft.identity.common.internal.msafederation.MsaFederatedSignInProviderName import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue @@ -42,7 +42,7 @@ class SignInWithGoogleParametersTest { fun testSignInWithGoogleParameters() { val activity = Robolectric.buildActivity(Activity::class.java).get() val signInWithGoogleParameters = SignInWithGoogleParameters(activity) - assertEquals(FederatedSignInProviderName.GOOGLE, signInWithGoogleParameters.providerName) + assertEquals(MsaFederatedSignInProviderName.GOOGLE, signInWithGoogleParameters.providerName) assertEquals(activity, signInWithGoogleParameters.activity) assertFalse(signInWithGoogleParameters.useBottomSheet) } @@ -51,7 +51,7 @@ class SignInWithGoogleParametersTest { fun testSignInWithGoogleParametersUseBottomSheet() { val activity = Robolectric.buildActivity(Activity::class.java).get() val signInWithGoogleParameters = SignInWithGoogleParameters(activity, true) - assertEquals(FederatedSignInProviderName.GOOGLE, signInWithGoogleParameters.providerName) + assertEquals(MsaFederatedSignInProviderName.GOOGLE, signInWithGoogleParameters.providerName) assertEquals(activity, signInWithGoogleParameters.activity) assertTrue(signInWithGoogleParameters.useBottomSheet) } diff --git a/common/src/test/java/com/microsoft/identity/common/internal/providers/oauth2/AuthorizationActivityFactoryTest.java b/common/src/test/java/com/microsoft/identity/common/internal/providers/oauth2/AuthorizationActivityFactoryTest.java index 6b4a95714a..bd380958f9 100644 --- a/common/src/test/java/com/microsoft/identity/common/internal/providers/oauth2/AuthorizationActivityFactoryTest.java +++ b/common/src/test/java/com/microsoft/identity/common/internal/providers/oauth2/AuthorizationActivityFactoryTest.java @@ -33,15 +33,22 @@ import static com.microsoft.identity.common.java.AuthenticationConstants.SdkPlatformFields.VERSION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import android.app.Activity; import android.content.Context; import android.content.Intent; +import com.microsoft.identity.common.internal.msafederation.google.SignInWithGoogleApi; import com.microsoft.identity.common.internal.msafederation.google.SignInWithGoogleCredential; +import com.microsoft.identity.common.internal.msafederation.google.SignInWithGoogleParameters; import com.microsoft.identity.common.java.ui.AuthorizationAgent; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; @@ -105,4 +112,61 @@ public void testGetAuthorizationActivityIntent() { assertNotNull(idTokenHeaderValue); assertEquals(idToken, idTokenHeaderValue); } + + @SneakyThrows + @Test + public void testSignInWithGoogleAndGetAuthorizationActivityIntent() { + // Arrange + final Context context = RuntimeEnvironment.getApplication(); + final Intent authIntent = new Intent(); + final String requestUrl = "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id=123&response_type=code&redirect_uri=msauth%3A%2F%2Fexample.com%2Fredirect"; + final String redirectUri = "msauth://example.com/redirect"; + final HashMap requestHeaders = new HashMap<>(); + requestHeaders.put("header1", "value1"); + final AuthorizationAgent authorizationAgent = AuthorizationAgent.WEBVIEW; + final boolean webViewZoomEnabled = true; + final boolean webViewZoomControlsEnabled = true; + final String sourceLibraryName = "TestLibrary"; + final String sourceLibraryVersion = "1.0.0"; + final String idToken = "idToken"; + final Activity mockActivity = Robolectric.buildActivity(Activity.class).get(); + // mock SignInWithGoogleApi using mockito + final SignInWithGoogleApi mockSignInWithGoogleApi = mock(SignInWithGoogleApi.class); + final SignInWithGoogleCredential mockCredential = new SignInWithGoogleCredential("idToken"); + when(mockSignInWithGoogleApi.signInSync(any(SignInWithGoogleParameters.class))).thenReturn(mockCredential); + + SignInWithGoogleApi.setInstance(mockSignInWithGoogleApi); + final SignInWithGoogleParameters siwgParams = new SignInWithGoogleParameters(mockActivity); + final Intent resultIntent = AuthorizationActivityFactory.signInWithGoogleAndGetAuthorizationActivityIntent( + context, + authIntent, + requestUrl, + redirectUri, + requestHeaders, + authorizationAgent, + webViewZoomEnabled, + webViewZoomControlsEnabled, + sourceLibraryName, + sourceLibraryVersion, + siwgParams + ); + + assertEquals(AuthorizationActivity.class.getName(), resultIntent.getComponent().getClassName()); + assertEquals(authIntent, resultIntent.getParcelableExtra(AUTH_INTENT)); + assertEquals(redirectUri, resultIntent.getStringExtra(REDIRECT_URI)); + assertEquals(authorizationAgent, resultIntent.getSerializableExtra(AUTHORIZATION_AGENT)); + assertEquals(webViewZoomEnabled, resultIntent.getBooleanExtra(WEB_VIEW_ZOOM_ENABLED, false)); + assertEquals(webViewZoomControlsEnabled, resultIntent.getBooleanExtra(WEB_VIEW_ZOOM_CONTROLS_ENABLED, false)); + assertEquals(sourceLibraryName, resultIntent.getStringExtra(PRODUCT)); + assertEquals(sourceLibraryVersion, resultIntent.getStringExtra(VERSION)); + + final String receivedUrl = resultIntent.getStringExtra(REQUEST_URL); + final String expectedUrl = requestUrl + "&id_provider=google.com"; + assertEquals(expectedUrl, receivedUrl); + + final HashMap receivedHeaders = (HashMap) resultIntent.getSerializableExtra(REQUEST_HEADERS); + final String idTokenHeaderValue = receivedHeaders.get("x-ms-fidp-idtoken"); + assertNotNull(idTokenHeaderValue); + assertEquals(idToken, idTokenHeaderValue); + } } 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 514a0b7352..6658e9b886 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 @@ -26,16 +26,18 @@ import static com.microsoft.identity.common.adal.internal.AuthenticationConstants.Broker.REQUEST_AUTHORITY; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import android.os.Bundle; import androidx.test.core.app.ApplicationProvider; import com.microsoft.identity.common.adal.internal.AuthenticationConstants; -import com.microsoft.identity.common.components.AndroidPlatformComponentsFactory; import com.microsoft.identity.common.components.MockPlatformComponentsFactory; import com.microsoft.identity.common.internal.broker.BrokerRequest; -import com.microsoft.identity.common.internal.commands.parameters.AndroidActivityInteractiveTokenCommandParameters; +import com.microsoft.identity.common.internal.commands.parameters.AndroidInteractiveTokenCommandParameters; +import com.microsoft.identity.common.internal.msafederation.google.SignInWithGoogleCredential; +import com.microsoft.identity.common.internal.msafederation.google.SignInWithGoogleParameters; import com.microsoft.identity.common.java.authorities.AzureActiveDirectoryAuthority; import com.microsoft.identity.common.java.authorities.AzureActiveDirectoryB2CAuthority; import com.microsoft.identity.common.java.authscheme.BearerAuthenticationSchemeInternal; @@ -47,7 +49,6 @@ import com.microsoft.identity.common.java.ui.BrowserDescriptor; import com.microsoft.identity.common.java.util.StringUtil; -import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @@ -175,6 +176,56 @@ public void test_BrokerRequestFromAcquireTokenParameters_SuppressBrokerPicker() test_BrokerRequestFromAcquireTokenParametersInternal(true); } + @Test + public void test_BrokerRequestFromAcquireTokenParameters_SignInWithGoogleParameters() { + final Set scopes = new HashSet<>(); + scopes.add("user.read"); + + final IPlatformComponents components = MockPlatformComponentsFactory.getNonFunctionalBuilder().build(); + final SignInWithGoogleCredential signInWithGoogleCredential = new SignInWithGoogleCredential("mock-id_token"); + final AndroidInteractiveTokenCommandParameters params = AndroidInteractiveTokenCommandParameters.builder() + .platformComponents(components) + .correlationId("987d8962-3f4d-4054-a852-ac0c4b6a602e") + .clientId("4b0db8c2-9f26-4417-8bde-3f0e3656f8e0") + .redirectUri("msauth://com.microsoft.identity.client.sample.local/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D") + .applicationName("com.microsoft.identity.client.sample.local") + .applicationVersion("1.0.0") + .childClientId("child_client_id") + .childRedirectUri("child_redirect_uri") + .loginHint("login_hint") + .sdkType(SdkType.MSAL) + .sdkVersion("5.4.0") + .authority(new AzureActiveDirectoryAuthority()) + .scopes(scopes) + .authenticationScheme(new BearerAuthenticationSchemeInternal()) + .prompt(OpenIdConnectPromptParameter.LOGIN) + .requiredBrokerProtocolVersion("10.0") + .suppressBrokerAccountPicker(true) + .preferredBrowser(new BrowserDescriptor("chrome", "signature", null, null)) + .claimsRequestJson("claims_request") + .brokerBrowserSupportEnabled(true) + .signInWithGoogleCredential(signInWithGoogleCredential) + .build(); + final MsalBrokerRequestAdapter msalBrokerRequestAdapter = new MsalBrokerRequestAdapter(); + final BrokerRequest brokerRequest = msalBrokerRequestAdapter.brokerRequestFromAcquireTokenParameters(params); + assertEquals(params.getCorrelationId(), brokerRequest.getCorrelationId()); + assertEquals(params.getClientId(), brokerRequest.getClientId()); + assertEquals(params.getRedirectUri(), brokerRequest.getRedirect()); + assertEquals(params.getApplicationName(), brokerRequest.getApplicationName()); + assertEquals(params.getApplicationVersion(), brokerRequest.getApplicationVersion()); + assertEquals(params.getChildClientId(), brokerRequest.getChildClientId()); + assertEquals(params.getChildRedirectUri(), brokerRequest.getChildRedirectUri()); + assertEquals(params.getLoginHint(), brokerRequest.getUserName()); + assertEquals(params.getSdkType(), brokerRequest.getSdkType()); + assertEquals(params.getSdkVersion(), brokerRequest.getMsalVersion()); + assertEquals(params.getAuthority().getAuthorityURL().toString(), brokerRequest.getAuthority()); + assertEquals(StringUtil.join(" ", scopes), brokerRequest.getScope()); + assertEquals(params.getAuthenticationScheme(), brokerRequest.getAuthenticationScheme()); + assertEquals(params.getPrompt().name(), brokerRequest.getPrompt()); + assertEquals(params.isSuppressBrokerAccountPicker(), brokerRequest.isSuppressAccountPicker()); + assertEquals(signInWithGoogleCredential, brokerRequest.getSignInWithGoogleCredential()); + } + private void test_BrokerRequestFromAcquireTokenParametersInternal(final boolean suppressBrokerAccountPicker) { final Set scopes = new HashSet<>(); scopes.add("user.read"); @@ -220,5 +271,6 @@ private void test_BrokerRequestFromAcquireTokenParametersInternal(final boolean assertEquals(params.getAuthenticationScheme(), brokerRequest.getAuthenticationScheme()); assertEquals(params.getPrompt().name(), brokerRequest.getPrompt()); assertEquals(params.isSuppressBrokerAccountPicker(), brokerRequest.isSuppressAccountPicker()); + assertNull(brokerRequest.getSignInWithGoogleCredential()); } }