Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automate test cases for MWPJ scenarios. #1817

Merged
merged 30 commits into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1df35cd
draft
p3dr0rv Apr 28, 2023
aa7116b
update test cases
p3dr0rv May 2, 2023
50e8947
Merge branch 'dev' into pedroro/mwpj-ui-test
p3dr0rv May 2, 2023
ac7398a
update test cases
p3dr0rv May 2, 2023
61d0c22
nits
p3dr0rv May 2, 2023
f4d6b9f
update common
p3dr0rv May 2, 2023
b35d6b1
add @LocalBrokerHostDebugUiTest
p3dr0rv May 3, 2023
a12a631
update common
p3dr0rv May 3, 2023
283c3bf
add 3 more test cases
p3dr0rv May 5, 2023
77c24ea
Merge branch 'dev' into pedroro/mwpj-ui-test
p3dr0rv May 15, 2023
79ed44e
addressing comments
p3dr0rv May 15, 2023
359167a
remove rules
p3dr0rv May 15, 2023
1df4a4f
extend TestCase2521960
p3dr0rv May 15, 2023
b52d9ad
update test cases
p3dr0rv May 19, 2023
b2ae6d1
update common
p3dr0rv May 20, 2023
3cef81b
update test case TestCase1600567
p3dr0rv May 20, 2023
61d123c
update common
p3dr0rv May 21, 2023
e935385
update TestCase1600567
p3dr0rv May 21, 2023
40d53c5
fix test_2579654
p3dr0rv May 22, 2023
24b5dc9
activate test case
p3dr0rv May 24, 2023
5301a00
update common
p3dr0rv May 24, 2023
dd9b2c5
update 2563668
p3dr0rv May 24, 2023
22bc361
feedback
p3dr0rv May 25, 2023
52b0ddf
Merge branch 'dev' into pedroro/mwpj-ui-test
p3dr0rv May 25, 2023
d475b2e
update commmon
p3dr0rv May 25, 2023
11015ba
add claim
p3dr0rv May 25, 2023
4a6f4e8
fix test TestCase2563668
p3dr0rv May 25, 2023
86e143b
nit kotlin do noty need semicolons
p3dr0rv May 25, 2023
0bdf619
remove duplicated steps from similar test cases
p3dr0rv May 26, 2023
eddb835
update common
p3dr0rv May 26, 2023
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
2 changes: 1 addition & 1 deletion common
Submodule common updated 40 files
+7 −1 changelog.txt
+14 −2 common/src/main/java/com/microsoft/identity/common/adal/internal/AuthenticationConstants.java
+2 −2 common/src/main/java/com/microsoft/identity/common/components/AndroidStorageSupplier.kt
+0 −91 common/src/main/java/com/microsoft/identity/common/exception/BrokerCommunicationException.java
+69 −0 common/src/main/java/com/microsoft/identity/common/exception/BrokerCommunicationException.kt
+96 −0 ...main/java/com/microsoft/identity/common/internal/activebrokerdiscovery/AccountManagerBrokerDiscoveryUtil.kt
+198 −0 common/src/main/java/com/microsoft/identity/common/internal/activebrokerdiscovery/BrokerDiscoveryClient.kt
+38 −0 common/src/main/java/com/microsoft/identity/common/internal/activebrokerdiscovery/IBrokerDiscoveryClient.kt
+0 −103 common/src/main/java/com/microsoft/identity/common/internal/broker/BrokerAccountServiceClient.java
+56 −3 common/src/main/java/com/microsoft/identity/common/internal/broker/BrokerData.kt
+12 −4 common/src/main/java/com/microsoft/identity/common/internal/broker/PackageHelper.java
+71 −0 ...src/main/java/com/microsoft/identity/common/internal/broker/ipc/AbstractIpcStrategyWithServiceValidation.kt
+95 −0 common/src/main/java/com/microsoft/identity/common/internal/broker/ipc/AccountManagerAddAccountStrategy.java
+17 −3 common/src/main/java/com/microsoft/identity/common/internal/broker/ipc/BoundServiceStrategy.java
+50 −13 common/src/main/java/com/microsoft/identity/common/internal/broker/ipc/BrokerOperationBundle.java
+14 −4 common/src/main/java/com/microsoft/identity/common/internal/broker/ipc/ContentProviderStrategy.java
+3 −0 common/src/main/java/com/microsoft/identity/common/internal/broker/ipc/IIpcStrategy.java
+8 −2 common/src/main/java/com/microsoft/identity/common/internal/controllers/BrokerMsalController.java
+7 −8 common/src/main/java/com/microsoft/identity/common/internal/request/MsalBrokerRequestAdapter.java
+2 −3 common/src/main/java/com/microsoft/identity/common/internal/ui/webview/AzureActiveDirectoryWebViewClient.java
+21 −3 common/src/main/java/com/microsoft/identity/common/internal/ui/webview/certbasedauth/CertBasedAuthFactory.java
+1 −10 .../com/microsoft/identity/common/internal/ui/webview/certbasedauth/OnDeviceCertBasedAuthChallengeHandler.java
+2 −3 common/src/main/java/com/microsoft/identity/common/internal/util/PackageUtils.java
+225 −0 ...java/com/microsoft/identity/common/internal/activebrokerdiscovery/AccountManagerBrokerDiscoveryUtilTests.kt
+376 −0 ...on/src/test/java/com/microsoft/identity/common/internal/activebrokerdiscovery/BrokerDiscoveryClientTests.kt
+49 −0 common/src/test/java/com/microsoft/identity/common/internal/activebrokerdiscovery/InMemoryActiveBrokerCache.kt
+7 −3 common/src/test/java/com/microsoft/identity/common/internal/broker/ipc/AccountManagerBoundServiceTests.java
+5 −5 common/src/test/java/com/microsoft/identity/common/internal/broker/ipc/ContentProviderStrategyTests.java
+118 −0 common/src/test/java/com/microsoft/identity/common/internal/ipc/AccountManagerAddAccountStrategyTest.java
+1 −1 common/src/test/java/com/microsoft/identity/common/internal/ipc/IpcStrategyTests.java
+68 −0 ...st/java/com/microsoft/identity/common/internal/ipc/mock/ShadowAccountManagerAddAccountConnectionFailed.java
+70 −0 ...t/java/com/microsoft/identity/common/internal/ipc/mock/ShadowAccountManagerAddAccountWithSuccessResult.java
+1 −1 common4j/versioning/version.properties
+27 −3 uiautomationutilities/src/main/java/com/microsoft/identity/client/ui/automation/broker/AbstractBrokerHost.java
+12 −3 uiautomationutilities/src/main/java/com/microsoft/identity/client/ui/automation/broker/AbstractTestBroker.java
+16 −0 ...mationutilities/src/main/java/com/microsoft/identity/client/ui/automation/broker/BrokerFlightsFragment.java
+112 −91 uiautomationutilities/src/main/java/com/microsoft/identity/client/ui/automation/broker/BrokerHost.java
+294 −0 ...ationutilities/src/main/java/com/microsoft/identity/client/ui/automation/broker/MultipleWpjApiFragment.java
+21 −73 ...omationutilities/src/main/java/com/microsoft/identity/client/ui/automation/broker/SingleWpjApiFragment.java
+1 −1 versioning/version.properties
8 changes: 6 additions & 2 deletions msalautomationapp/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

def msalVersion = "4.+"

Expand Down Expand Up @@ -146,12 +147,12 @@ android {
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java']
java.srcDirs = ['src/main/java', 'src/main/kotlin']
}

androidTest {
manifest.srcFile 'src/androidTest/AndroidManifest.xml'
res.srcDirs = ['src/main/res']
res.srcDirs = ['src/main/res', 'src/main/kotlin']
}
}
}
Expand Down Expand Up @@ -184,5 +185,8 @@ dependencies {
}
androidTestImplementation "androidx.test:runner:$rootProject.ext.androidxTestRunnerVersion"
androidTestUtil "androidx.test:orchestrator:$rootProject.ext.androidxTestOrchestratorVersion"
implementation "org.jetbrains.kotlin:kotlin-stdlib:${rootProject.ext.kotlinVersion}"
testImplementation "org.jetbrains.kotlin:kotlin-stdlib:${rootProject.ext.kotlinVersion}"
androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib:${rootProject.ext.kotlinVersion}"
}

Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,27 @@
// THE SOFTWARE.
package com.microsoft.identity.client.msal.automationapp.testpass.broker.brokerapi;

import android.util.Base64;

import androidx.annotation.NonNull;

import com.google.gson.Gson;
import com.microsoft.identity.client.msal.automationapp.R;
import com.microsoft.identity.client.msal.automationapp.testpass.broker.AbstractMsalBrokerTest;
import com.microsoft.identity.client.ui.automation.annotations.LocalBrokerHostDebugUiTest;
import com.microsoft.identity.client.ui.automation.annotations.RetryOnFailure;
import com.microsoft.identity.client.ui.automation.annotations.SupportedBrokers;
import com.microsoft.identity.client.ui.automation.broker.BrokerHost;
import com.microsoft.identity.common.java.util.StringUtil;
import com.microsoft.identity.labapi.utilities.client.LabQuery;
import com.microsoft.identity.labapi.utilities.constants.TempUserType;

import org.junit.Assert;
import org.junit.Test;

import java.util.Map;
import java.util.Set;

// SSO Token Requests
// https://identitydivision.visualstudio.com/Engineering/_workitems/edit/1561652
@SupportedBrokers(brokers = {BrokerHost.class})
Expand All @@ -50,7 +60,7 @@ public void test_1561652() {
// Get SSO token and decode to confirm nonce
final String ssoToken = ((BrokerHost) mBroker).acquireSSOToken(nonce);

((BrokerHost) mBroker).decodeSSOTokenAndVerifyNonce(ssoToken, nonce);
decodeSSOTokenAndVerifyNonce(ssoToken, nonce);
}

@Override
Expand All @@ -77,4 +87,32 @@ public String getAuthority() {
public int getConfigFileResourceId() {
return R.raw.msal_config_default;
}

/**
* Decode SSO token and verify the expected nonce
*/
public void decodeSSOTokenAndVerifyNonce(@NonNull final String ssoToken,
@NonNull final String nonce) {
Assert.assertFalse("Passed an empty or null token", StringUtil.isNullOrEmpty(ssoToken));
String token = new String(Base64.decode(ssoToken.split("\\.")[1], Base64.NO_WRAP));
final Map<Object, Object> map = new Gson().fromJson(token, Map.class);
StringBuilder sb = new StringBuilder();
final Set<Map.Entry<Object, Object>> set = map.entrySet();
for (Map.Entry<Object, Object> e : set) {
sb.append(e.getKey()).append(" => ")
.append(e.getValue())
.append('\n');
}
final String decodedToken = sb.toString();
if (decodedToken.contains("request_nonce")) {
final String[] str = decodedToken.split("request_nonce => ");
if (str.length > 1) {
Assert.assertEquals(str[1].trim(), nonce);
} else {
Assert.fail("decoded token does not contain correct nonce");
}
} else {
Assert.fail("decoded token does not contain correct nonce");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.microsoft.identity.labapi.utilities.constants.AzureEnvironment;
import com.microsoft.identity.labapi.utilities.constants.TempUserType;

import org.junit.Assert;
import org.junit.Test;

// Invoke each API from non-allowed apps. the request should be blocked.
Expand All @@ -51,7 +52,7 @@ public void test_1600567() throws Throwable {
brokerHost.brokerApiFragment.launch();
// verify getAccounts call gives calling app not verified
UiAutomatorUtils.handleButtonClick("com.microsoft.identity.testuserapp:id/button_get_accounts");
brokerHost.confirmCallingAppNotVerified();
confirmCallingAppNotVerified();

// verify removeAccount call gives calling app not verified
final UiObject usernameTxt = UiAutomatorUtils.obtainChildInScrollable("someone@contoso.com");
Expand All @@ -60,7 +61,7 @@ public void test_1600567() throws Throwable {
"com.microsoft.identity.testuserapp:id/button_remove_account"
);
removeAccount.click();
brokerHost.confirmCallingAppNotVerified();
confirmCallingAppNotVerified();

// verify update BRT call gives calling app not verified
// fill BRT
Expand All @@ -69,18 +70,18 @@ public void test_1600567() throws Throwable {
UiAutomatorUtils.handleInput("com.microsoft.identity.testuserapp:id/edit_text_home_authority", "https://login.microsoftonline.com/common");
// click on update BRT
UiAutomatorUtils.handleButtonClick("com.microsoft.identity.testuserapp:id/button_update_brt");
brokerHost.confirmCallingAppNotVerified();
confirmCallingAppNotVerified();

brokerHost.brokerFlightsFragment.launch();
// verify setFlights call gives calling app not verified
UiAutomatorUtils.handleButtonClick("com.microsoft.identity.testuserapp:id/flight_provider_local_storage");
UiAutomatorUtils.handleInput("com.microsoft.identity.testuserapp:id/edit_text_flights", "{test : true}");
UiAutomatorUtils.handleButtonClick("com.microsoft.identity.testuserapp:id/button_set_flights");
brokerHost.confirmCallingAppNotVerified();
confirmCallingAppNotVerified();

// verify getFlights call gives calling app not verified
UiAutomatorUtils.handleButtonClick("com.microsoft.identity.testuserapp:id/button_get_flights");
brokerHost.confirmCallingAppNotVerified();
confirmCallingAppNotVerified();
}


Expand Down Expand Up @@ -110,5 +111,14 @@ public String getAuthority() {
public int getConfigFileResourceId() {
return R.raw.msal_config_default;
}

/**
* Confirm that the calling app is not verified
*/
public void confirmCallingAppNotVerified() {
String dialogMessage = ((BrokerHost)getBroker()).dismissDialog();
Assert.assertTrue(dialogMessage.contains("Calling app could not be verified"));
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,19 @@
package com.microsoft.identity.client.msal.automationapp.testpass.broker.brokerapi;


import androidx.annotation.Nullable;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.UiSelector;

import com.microsoft.identity.client.msal.automationapp.R;
import com.microsoft.identity.client.msal.automationapp.testpass.broker.AbstractMsalBrokerTest;
import com.microsoft.identity.client.ui.automation.annotations.LocalBrokerHostDebugUiTest;
import com.microsoft.identity.client.ui.automation.annotations.SupportedBrokers;
import com.microsoft.identity.client.ui.automation.broker.BrokerHost;
import com.microsoft.identity.client.ui.automation.utils.UiAutomatorUtils;
import com.microsoft.identity.labapi.utilities.client.LabQuery;
import com.microsoft.identity.labapi.utilities.constants.TempUserType;
import com.microsoft.identity.labapi.utilities.constants.UserType;
Expand All @@ -41,12 +49,12 @@
@SupportedBrokers(brokers = BrokerHost.class)
@LocalBrokerHostDebugUiTest
public class TestCase2110359 extends AbstractMsalBrokerTest{
// tenant id where lab api and key vault api is registered
private final static String LAB_API_TENANT_ID = "72f988bf-86f1-41af-91ab-2d7cd011db47";

@Test
public void test_2110359() {
BrokerHost brokerHost = (BrokerHost) mBroker;

brokerHost.checkForDcfOption(null);
checkForDcfOption(null);
}

@Override
Expand Down Expand Up @@ -75,4 +83,42 @@ public String getAuthority() {
public int getConfigFileResourceId() {
return R.raw.msal_config_default;
}

/**
* Check if the Device Code Flow option shows up in sign in flow.
*
* @param tenantId tenant ID to use in Join Tenant
*/
public void checkForDcfOption(@Nullable final String tenantId) {
final String tenantIdToUse;

// If no tenant ID is specified, default to microsoft tenant
if (tenantId == null) {
tenantIdToUse = LAB_API_TENANT_ID;
} else {
tenantIdToUse = tenantId;
}
BrokerHost brokerHost = (BrokerHost) mBroker;
brokerHost.launch();
brokerHost.clickJoinTenant(tenantIdToUse);

// Apparently, there are two UI objects with exact text "Sign-in options", one is a button the other is a view
// Have to specify the search to button class
final UiDevice device =
UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());

final UiObject optionsObject = device.findObject(new UiSelector()
.text("Sign-in options").className("android.widget.Button"));

try {
optionsObject.click();
} catch (UiObjectNotFoundException e) {
throw new AssertionError(e);
}
UiAutomatorUtils.handleButtonClickForObjectWithText("Sign in from another device");

// Doesn't look like the page with the device code is readable to the UI automation,
// this is a sufficient stopping point
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// 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.client.msal.automationapp.testpass.broker.mwpj

import com.microsoft.identity.client.msal.automationapp.R
import com.microsoft.identity.client.msal.automationapp.testpass.broker.AbstractMsalBrokerTest
import com.microsoft.identity.client.ui.automation.annotations.LocalBrokerHostDebugUiTest
import com.microsoft.identity.client.ui.automation.annotations.SupportedBrokers
import com.microsoft.identity.client.ui.automation.broker.BrokerHost
import com.microsoft.identity.labapi.utilities.client.ILabAccount
import com.microsoft.identity.labapi.utilities.client.LabQuery
import com.microsoft.identity.labapi.utilities.constants.AzureEnvironment
import com.microsoft.identity.labapi.utilities.constants.TempUserType
import com.microsoft.identity.labapi.utilities.constants.UserType
import org.junit.Assert
import org.junit.Before
import org.junit.Test

// https://identitydivision.visualstudio.com/Engineering/_workitems/edit/2519783
p3dr0rv marked this conversation as resolved.
Show resolved Hide resolved
// [MWPJ] Install WPJ certificate for browser access in both registrations.
@LocalBrokerHostDebugUiTest
@SupportedBrokers(brokers = [BrokerHost::class])
class TestCase2519783 : AbstractMsalBrokerTest() {

private lateinit var mUsGovAccount: ILabAccount
private lateinit var mBrokerHostApp: BrokerHost

@Test
fun test_2519783() {
// Register 2 accounts from different tenants
mBrokerHostApp.multipleWpjApiFragment.performDeviceRegistration(mLabAccount.username, mLabAccount.password)
mBrokerHostApp.multipleWpjApiFragment.performDeviceRegistration(mUsGovAccount.username, mUsGovAccount.password)
val deviceRegistrationRecords = mBrokerHostApp.multipleWpjApiFragment.allRecords
Assert.assertEquals(2, deviceRegistrationRecords.size)

// Install WPJ certificate for browser access in both registrations.
mBrokerHostApp.multipleWpjApiFragment.installCertificate(deviceRegistrationRecords[0]["TenantId"] as String)
mBrokerHostApp.multipleWpjApiFragment.installCertificate(deviceRegistrationRecords[1]["TenantId"] as String)
}

override fun getLabQuery(): LabQuery {
return LabQuery.builder()
.userType(UserType.CLOUD)
.build()
}

override fun getTempUserType(): TempUserType? {
return null
}

private fun getUsGovLabQuery(): LabQuery {
return LabQuery.builder()
.userType(UserType.CLOUD)
.azureEnvironment(AzureEnvironment.AZURE_US_GOVERNMENT)
.build()
}

@Before
fun before() {
mUsGovAccount = mLabClient.getLabAccount(getUsGovLabQuery())
mBrokerHostApp = broker as BrokerHost
mBrokerHostApp.enableMultipleWpj()
}

/**
* Get the scopes that can be used for an acquire token test.
*
* @return A string array consisting of OAUTH2 Scopes
*/
override fun getScopes(): Array<String> {
return arrayOf("User.read")
}

/**
* Get the authority url that can be used for an acquire token test.
*
* @return A string representing the url for an authority that can be used as token issuer
*/
override fun getAuthority(): String {
return mApplication.configuration.defaultAuthority.authorityURL.toString()
}

/**
* The MSAL config file that should be used to create a PublicClientApplication for the test.
*
* @return config file resource id
*/
override fun getConfigFileResourceId(): Int {
return R.raw.msal_config_default
}
}
Loading
Loading