Skip to content

Commit 8d060c2

Browse files
authored
Merge pull request #1365 from AzureAD/release/2.0.10
Release/2.0.10
2 parents 7c5f93d + 208cde8 commit 8d060c2

28 files changed

+978
-225
lines changed

changelog

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
MSAL Wiki : https://github.com/AzureAD/microsoft-authentication-library-for-android/wiki
2+
Version 2.0.10
3+
----------
4+
- [PATCH] Add extra '/' in the example intent filter (#1323)
5+
- [PATCH] Better PublicClientApplicationConfiguration validation to fail when empty string is passed (#1324)
6+
- [PATCH] Improve redirect_uri validation of PCA manifest (#1327)
7+
28

39
Version 2.0.8
410
----------
5-
- [MINOR] Changes to Broker Validation to allow setting whether to trust debug brokers (prod brokers are always trusted).
11+
- [MINOR] Changes to Broker Validation to allow setting whether to trust debug brokers (prod brokers are always trusted) (#1274)
12+
613

714
Version 2.0.6
815
----------

common

Submodule common updated 98 files

msal/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,9 @@ dependencies {
274274
transitive = false
275275
}
276276

277-
snapshotApi(group: 'com.microsoft.identity', name: 'common', version: '3.1.2', changing: true)
277+
snapshotApi(group: 'com.microsoft.identity', name: 'common', version: '3.3.1', changing: true)
278278

279-
distApi("com.microsoft.identity:common:3.1.2") {
279+
distApi("com.microsoft.identity:common:3.3.1") {
280280
transitive = false
281281
}
282282
}

msal/src/androidTest/java/com/microsoft/identity/client/PublicClientApplicationTest.java

Lines changed: 86 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,29 @@ public void tearDown() {
106106
AndroidTestUtil.removeAllTokens(mAppContext);
107107
}
108108

109+
@Test(expected = IllegalArgumentException.class)
110+
public void testConfigValidationFailsOnEmptyRedirect() throws MsalException, InterruptedException {
111+
final Context context = new PublicClientApplicationTest.MockContext(mAppContext);
112+
mockPackageManagerWithDefaultFlag(context);
113+
mockHasCustomTabRedirect(context);
114+
115+
final IMultipleAccountPublicClientApplication app = PublicClientApplication.createMultipleAccountPublicClientApplication(
116+
context,
117+
R.raw.test_pcaconfig_empty_redirect
118+
);
119+
}
120+
121+
@Test(expected = IllegalArgumentException.class)
122+
public void testConfigValidationFailsOnEmptyClientId() throws MsalException, InterruptedException {
123+
final Context context = new PublicClientApplicationTest.MockContext(mAppContext);
124+
mockPackageManagerWithDefaultFlag(context);
125+
mockHasCustomTabRedirect(context);
126+
127+
final IMultipleAccountPublicClientApplication app = PublicClientApplication.createMultipleAccountPublicClientApplication(
128+
context,
129+
R.raw.test_pcaconfig_empty_clientid
130+
);
131+
}
109132

110133
@Test
111134
public void testSingleAccountConstructor() {
@@ -114,7 +137,10 @@ public void testSingleAccountConstructor() {
114137
mockHasCustomTabRedirect(context);
115138

116139
try {
117-
ISingleAccountPublicClientApplication app = PublicClientApplication.createSingleAccountPublicClientApplication(context, R.raw.test_msal_config_single_account);
140+
final ISingleAccountPublicClientApplication app = PublicClientApplication.createSingleAccountPublicClientApplication(
141+
context,
142+
R.raw.test_msal_config_single_account
143+
);
118144
Assert.assertTrue(app instanceof ISingleAccountPublicClientApplication);
119145
} catch (InterruptedException e) {
120146
e.printStackTrace();
@@ -130,7 +156,10 @@ public void testMultipleAccountConstructor() {
130156
mockHasCustomTabRedirect(context);
131157

132158
try {
133-
IMultipleAccountPublicClientApplication app = PublicClientApplication.createMultipleAccountPublicClientApplication(context, R.raw.test_msal_config_multiple_account);
159+
final IMultipleAccountPublicClientApplication app = PublicClientApplication.createMultipleAccountPublicClientApplication(
160+
context,
161+
R.raw.test_msal_config_multiple_account
162+
);
134163
Assert.assertTrue(app instanceof IMultipleAccountPublicClientApplication);
135164
} catch (InterruptedException e) {
136165
e.printStackTrace();
@@ -145,17 +174,20 @@ public void testMultipleAccountAsyncConstructor() {
145174
mockPackageManagerWithDefaultFlag(context);
146175
mockHasCustomTabRedirect(context);
147176

148-
PublicClientApplication.createMultipleAccountPublicClientApplication(context, R.raw.test_msal_config_multiple_account, new PublicClientApplication.IMultipleAccountApplicationCreatedListener() {
149-
@Override
150-
public void onCreated(IMultipleAccountPublicClientApplication application) {
151-
Assert.assertTrue(application instanceof IMultipleAccountPublicClientApplication);
152-
}
153-
154-
@Override
155-
public void onError(MsalException exception) {
156-
Assert.assertTrue(false);
157-
}
158-
});
177+
PublicClientApplication.createMultipleAccountPublicClientApplication(
178+
context,
179+
R.raw.test_msal_config_multiple_account,
180+
new PublicClientApplication.IMultipleAccountApplicationCreatedListener() {
181+
@Override
182+
public void onCreated(IMultipleAccountPublicClientApplication application) {
183+
Assert.assertTrue(application instanceof IMultipleAccountPublicClientApplication);
184+
}
185+
186+
@Override
187+
public void onError(MsalException exception) {
188+
Assert.assertTrue(false);
189+
}
190+
});
159191
}
160192

161193
@Test
@@ -164,17 +196,20 @@ public void testFailingMultipleAccountAsyncConstructor() {
164196
mockPackageManagerWithDefaultFlag(context);
165197
mockHasCustomTabRedirect(context);
166198

167-
PublicClientApplication.createMultipleAccountPublicClientApplication(context, R.raw.test_msal_config_single_account, new PublicClientApplication.IMultipleAccountApplicationCreatedListener() {
168-
@Override
169-
public void onCreated(IMultipleAccountPublicClientApplication application) {
170-
Assert.assertTrue(false);
171-
}
172-
173-
@Override
174-
public void onError(MsalException exception) {
175-
Assert.assertTrue("Expecting error.", true);
176-
}
177-
});
199+
PublicClientApplication.createMultipleAccountPublicClientApplication(
200+
context,
201+
R.raw.test_msal_config_single_account,
202+
new PublicClientApplication.IMultipleAccountApplicationCreatedListener() {
203+
@Override
204+
public void onCreated(IMultipleAccountPublicClientApplication application) {
205+
Assert.assertTrue(false);
206+
}
207+
208+
@Override
209+
public void onError(MsalException exception) {
210+
Assert.assertTrue("Expecting error.", true);
211+
}
212+
});
178213
}
179214

180215
@Test
@@ -183,16 +218,19 @@ public void testSingleAccountAsyncConstructor() {
183218
mockPackageManagerWithDefaultFlag(context);
184219
mockHasCustomTabRedirect(context);
185220

186-
PublicClientApplication.createSingleAccountPublicClientApplication(context, R.raw.test_msal_config_single_account, new PublicClientApplication.ISingleAccountApplicationCreatedListener() {
187-
@Override
188-
public void onCreated(ISingleAccountPublicClientApplication application) {
189-
Assert.assertTrue(application instanceof ISingleAccountPublicClientApplication);
190-
}
191-
192-
@Override
193-
public void onError(MsalException exception) {
194-
}
195-
});
221+
PublicClientApplication.createSingleAccountPublicClientApplication(
222+
context,
223+
R.raw.test_msal_config_single_account,
224+
new PublicClientApplication.ISingleAccountApplicationCreatedListener() {
225+
@Override
226+
public void onCreated(ISingleAccountPublicClientApplication application) {
227+
Assert.assertTrue(application instanceof ISingleAccountPublicClientApplication);
228+
}
229+
230+
@Override
231+
public void onError(MsalException exception) {
232+
}
233+
});
196234
}
197235

198236
@Test
@@ -201,17 +239,20 @@ public void testFailingSingleAccountAsyncConstructor() {
201239
mockPackageManagerWithDefaultFlag(context);
202240
mockHasCustomTabRedirect(context);
203241

204-
PublicClientApplication.createSingleAccountPublicClientApplication(context, R.raw.test_msal_config_multiple_account, new PublicClientApplication.ISingleAccountApplicationCreatedListener() {
205-
@Override
206-
public void onCreated(ISingleAccountPublicClientApplication application) {
207-
Assert.assertTrue(false);
208-
}
209-
210-
@Override
211-
public void onError(MsalException exception) {
212-
Assert.assertTrue("Expecting error.", true);
213-
}
214-
});
242+
PublicClientApplication.createSingleAccountPublicClientApplication(
243+
context,
244+
R.raw.test_msal_config_multiple_account,
245+
new PublicClientApplication.ISingleAccountApplicationCreatedListener() {
246+
@Override
247+
public void onCreated(ISingleAccountPublicClientApplication application) {
248+
Assert.assertTrue(false);
249+
}
250+
251+
@Override
252+
public void onError(MsalException exception) {
253+
Assert.assertTrue("Expecting error.", true);
254+
}
255+
});
215256
}
216257

217258
/**

msal/src/androidTest/res/raw/test_msal_config_multiple_account.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
}
1414
}
1515
]
16-
}
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"client_id" : "",
3+
"authorization_user_agent" : "DEFAULT",
4+
"redirect_uri" : "msauth://com.microsoft.identity.client.sample.local/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D",
5+
"multiple_clouds_supported":true,
6+
"broker_redirect_uri_registered": true,
7+
"account_mode": "MULTIPLE",
8+
"authorities" : [
9+
{
10+
"type": "AAD",
11+
"audience": {
12+
"type": "AzureADandPersonalMicrosoftAccount"
13+
}
14+
}
15+
]
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"client_id" : "4b0db8c2-9f26-4417-8bde-3f0e3656f8e0",
3+
"authorization_user_agent" : "DEFAULT",
4+
"redirect_uri" : "",
5+
"multiple_clouds_supported":true,
6+
"broker_redirect_uri_registered": true,
7+
"account_mode": "MULTIPLE",
8+
"authorities" : [
9+
{
10+
"type": "AAD",
11+
"audience": {
12+
"type": "AzureADandPersonalMicrosoftAccount"
13+
}
14+
}
15+
]
16+
}

msal/src/main/java/com/microsoft/identity/client/AccountAdapter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ private static void appendChildren(@NonNull final List<IAccount> rootAccounts,
265265
null,
266266
getIdToken(guestRecord)
267267
);
268+
profile.setEnvironment(guestRecord.getAccount().getEnvironment());
268269
tenantProfiles.put(guestRecord.getAccount().getRealm(), profile);
269270
}
270271
}

msal/src/main/java/com/microsoft/identity/client/PublicClientApplicationConfiguration.java

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import android.content.pm.PackageManager;
2828
import android.content.pm.Signature;
2929
import android.net.Uri;
30+
import android.text.TextUtils;
3031
import android.util.Base64;
3132

3233
import androidx.annotation.NonNull;
@@ -73,11 +74,13 @@
7374
import static com.microsoft.identity.client.PublicClientApplicationConfiguration.SerializedNames.USE_BROKER;
7475
import static com.microsoft.identity.client.PublicClientApplicationConfiguration.SerializedNames.WEB_VIEW_ZOOM_CONTROLS_ENABLED;
7576
import static com.microsoft.identity.client.PublicClientApplicationConfiguration.SerializedNames.WEB_VIEW_ZOOM_ENABLED;
77+
import static com.microsoft.identity.client.exception.MsalClientException.APP_MANIFEST_VALIDATION_ERROR;
7678

7779
public class PublicClientApplicationConfiguration {
7880
private static final String TAG = PublicClientApplicationConfiguration.class.getSimpleName();
7981

8082
private static final String BROKER_REDIRECT_URI_SCHEME_AND_SEPARATOR = "msauth://";
83+
public static final String INVALID_REDIRECT_MSG = "Invalid, null, or malformed redirect_uri supplied";
8184

8285
public static final class SerializedNames {
8386
static final String CLIENT_ID = "client_id";
@@ -438,7 +441,7 @@ void mergeConfiguration(PublicClientApplicationConfiguration config) {
438441
}
439442

440443
void validateConfiguration() {
441-
nullConfigurationCheck(REDIRECT_URI, mRedirectUri);
444+
validateRedirectUri(mRedirectUri);
442445
nullConfigurationCheck(CLIENT_ID, mClientId);
443446
checkDefaultAuthoritySpecified();
444447

@@ -465,6 +468,27 @@ void validateConfiguration() {
465468
}
466469
}
467470

471+
private void validateRedirectUri(@NonNull final String redirectUri) {
472+
final boolean isInvalid = TextUtils.isEmpty(redirectUri) || !hasSchemeAndAuthority(redirectUri);
473+
474+
if (isInvalid) {
475+
throw new IllegalArgumentException(INVALID_REDIRECT_MSG);
476+
}
477+
}
478+
479+
private boolean hasSchemeAndAuthority(@NonNull final String redirectUri) {
480+
try {
481+
final Uri parsedRedirectUri = Uri.parse(redirectUri);
482+
final boolean hasScheme = !TextUtils.isEmpty(parsedRedirectUri.getScheme());
483+
final boolean hasAuthority = !TextUtils.isEmpty(parsedRedirectUri.getAuthority());
484+
return hasScheme && hasAuthority;
485+
} catch (final NullPointerException e) {
486+
Logger.errorPII(TAG, INVALID_REDIRECT_MSG, e);
487+
}
488+
489+
return false;
490+
}
491+
468492
private void validateAzureActiveDirectoryAuthority(@NonNull final AzureActiveDirectoryAuthority azureActiveDirectoryAuthority) {
469493
if (null != azureActiveDirectoryAuthority.mAudience
470494
&& azureActiveDirectoryAuthority.mAudience instanceof UnknownAudience) {
@@ -474,8 +498,8 @@ private void validateAzureActiveDirectoryAuthority(@NonNull final AzureActiveDir
474498
}
475499
}
476500

477-
private void nullConfigurationCheck(String configKey, String configValue) {
478-
if (configValue == null) {
501+
private static void nullConfigurationCheck(String configKey, String configValue) {
502+
if (TextUtils.isEmpty(configValue)) {
479503
throw new IllegalArgumentException(configKey + " cannot be null. Invalid configuration.");
480504
}
481505
}
@@ -529,7 +553,7 @@ public void checkIntentFilterAddedToAppManifestForBrokerFlow() throws MsalClient
529553
&& !hasCustomTabRedirectActivity) {
530554
final Uri redirectUri = Uri.parse(mRedirectUri);
531555
throw new MsalClientException(
532-
MsalClientException.APP_MANIFEST_VALIDATION_ERROR,
556+
APP_MANIFEST_VALIDATION_ERROR,
533557
"Intent filter for: " +
534558
BrowserTabActivity.class.getSimpleName() +
535559
" is missing. " +
@@ -555,8 +579,8 @@ public void checkIntentFilterAddedToAppManifestForBrokerFlow() throws MsalClient
555579
// This means that the app is still using the legacy local-only MSAL Redirect uri (already removed from the new portal).
556580
// If this is the case, we can assume that the user doesn't need Broker support.
557581
Logger.warn(TAG, "The app is still using legacy MSAL redirect uri. Switch to MSAL local auth."
558-
+ " For brokered auth, the redirect URI is expected to conform to 'msauth://<authority>/.*' where the authority in "
559-
+ "that uri is the package name of the app. This package name is listed as 'applicationId' in the build.gradle file.");
582+
+ " For brokered auth, the redirect URI is expected to conform to 'msauth://<authority>/.*' where the authority in "
583+
+ "that uri is the package name of the app. This package name is listed as 'applicationId' in the build.gradle file.");
560584
mUseBroker = false;
561585
return;
562586
}

msal/src/main/java/com/microsoft/identity/client/helper/BrokerHelperActivity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public class BrokerHelperActivity extends Activity {
2929
" <category android:name=\"android.intent.category.BROWSABLE\" />\n" +
3030
" <data\n" +
3131
" android:host=\"%s\"\n" +
32-
" android:path=\"%s\"\n" +
32+
" android:path=\"/%s\"\n" +
3333
" android:scheme=\"msauth\" />\n" +
3434
" </intent-filter>\n" +
3535
"</activity>";

0 commit comments

Comments
 (0)