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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ vNext
- [MINOR] Add Get AAD device ID API for resource account (#2644)
- [MINOR] Expose a JavaScript API in brokered Webviews to facilitate Improved Same Device NumberMatch (#2617)
- [MINOR] Add API for resource account provisioning (API only) (#2640)
- [PATCH] Fixing error in construction of LegacyFido2ApiManager (#2654)

Version 21.1.0
----------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class CredManFidoManager (val context: Context,
// We're setting preferImmediatelyAvailableCredentials in the CredMan getCredentialRequest object to true if the device OS is Android 13 or lower.
// This ensures the behavior where no dialog from CredMan is shown if no passkey cred is present.
// The end goal is for an Android <= 13 user who only has a security key to see one dialog which will allow them to authenticate.
preferImmediatelyAvailableCredentials = (getFlightsProvider().isFlightEnabled(CommonFlight.ENABLE_LEGACY_FIDO_SECURITY_KEY_LOGIC) && Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
preferImmediatelyAvailableCredentials = (legacyManager != null && getFlightsProvider().isFlightEnabled(CommonFlight.ENABLE_LEGACY_FIDO_SECURITY_KEY_LOGIC) && Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
)
try {
Logger.info(methodTag, "Calling Credential Manager with a GetCredentialRequest.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,11 +235,16 @@ private boolean handleUrl(final WebView view, final String url) {
} else if (CommonFlightsManager.INSTANCE.getFlightsProvider().isFlightEnabled(CommonFlight.ENABLE_PASSKEY_FEATURE) && isPasskeyUrl(formattedURL)) {
Logger.info(methodTag,"WebView detected request for passkey protocol.");
final FidoChallenge challenge = FidoChallenge.createFromRedirectUri(url);
final SpanContext spanContext = getActivity() instanceof AuthorizationActivity ? ((AuthorizationActivity)getActivity()).getSpanContext() : null;
final Activity currentActivity = getActivity();
final SpanContext spanContext = currentActivity instanceof AuthorizationActivity ? ((AuthorizationActivity)currentActivity).getSpanContext() : null;
// The legacyManager should only be getting added if the device is on Android 13 or lower and the library is MSAL/OneAuth with fragment or dialog mode.
// The legacyManager logic should be removed once a larger majority of users are on Android 14+.
final IFidoManager legacyManager =
CommonFlightsManager.INSTANCE.getFlightsProvider().isFlightEnabled(CommonFlight.ENABLE_LEGACY_FIDO_SECURITY_KEY_LOGIC)
currentActivity instanceof AuthorizationActivity
&& ((AuthorizationActivity) currentActivity).getFragment() instanceof WebViewAuthorizationFragment
&& CommonFlightsManager.INSTANCE.getFlightsProvider().isFlightEnabled(CommonFlight.ENABLE_LEGACY_FIDO_SECURITY_KEY_LOGIC)
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE
? new LegacyFido2ApiManager(view.getContext(), (WebViewAuthorizationFragment)((AuthorizationActivity)getActivity()).getFragment())
? new LegacyFido2ApiManager(view.getContext(), (WebViewAuthorizationFragment)((AuthorizationActivity)currentActivity).getFragment())
: null;
final AuthFidoChallengeHandler challengeHandler = new AuthFidoChallengeHandler(
new CredManFidoManager(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import androidx.test.core.app.ApplicationProvider;

import com.microsoft.identity.common.adal.internal.AuthenticationConstants;
import com.microsoft.identity.common.internal.ui.DualScreenActivity;
import com.microsoft.identity.common.internal.ui.webview.challengehandlers.CrossCloudChallengeHandler;
import com.microsoft.identity.common.java.exception.ClientException;
import com.microsoft.identity.common.java.providers.microsoft.azureactivedirectory.AzureActiveDirectory;
Expand Down Expand Up @@ -90,6 +91,7 @@ public class AzureActiveDirectoryWebViewClientTest {
private static final String TEST_NONCE_REDIRECT_URL = "https://login.microsoftonline.com/organizations/oAuth2/v2.0/authorize?&sso_nonce=ABCD";
private static final String TEST_CROSS_CLOUD_REDIRECT_URL = "https://login.microsoftonline.us/organizations/oAuth2/v2.0/authorize?x=10";
private static final String TEST_PUBLIC_CLOUD_REDIRECT_URL = "https://login.microsoftonline.com/organizations/oAuth2/v2.0/authorize?x=10";
private static final String TEST_PASSKEY_REDIRECT_URL = "http-auth:PassKey?challenge=challenge&version=1.0&submitUrl=https://login.microsoftonline.com/common/credential?passKeyAuth=1.0%2fpasskey&context=&relyingPartyIdentifier=login.microsoft.com&allowedCredentials=somevalue";
private static final String TEST_INTENT_INSTALL_BROKER_REDIRECT_URL = "intent://play.google.com/store/apps/details?id=com.azure.authenticator&referrer=%20adjust_reftag%3Dc6f1p4ErudH2C%26utm_source%3DLanding%2BPage%2BOrganic%2B-%2Bapp%2Bstore%2Bbadges%26utm_campaign%3Dappstore_android&pcampaignid=web_auto_redirect&web_logged_in=0&redirect_entry_point=dp#Intent;scheme=https;action=android.intent.action.VIEW;package=com.android.vending;end";

@Before
Expand Down Expand Up @@ -236,8 +238,45 @@ public void testProcessCloudRedirectAndPrtHeaderInternalException() {
}
}

@Test
public void testUrlOverrideHandlesIntentRedirectUrl() {
assertTrue(mWebViewClient.shouldOverrideUrlLoading(mMockWebView, TEST_INTENT_INSTALL_BROKER_REDIRECT_URL));
}

public void setTestPasskeyRedirectUrl() {
assertTrue(mWebViewClient.shouldOverrideUrlLoading(mMockWebView, TEST_PASSKEY_REDIRECT_URL));
}

@Test
public void testPasskeyActivityCastingNoException() {
try {
// Putting an explicit non-AuthorizationActivity activity here to test that an exception won't be thrown.
mActivity = Robolectric.buildActivity(DualScreenActivity.class).get();
mWebViewClient = new AzureActiveDirectoryWebViewClient(
mActivity,
new IAuthorizationCompletionCallback() {
@Override
public void onChallengeResponseReceived(@NonNull RawAuthorizationResult response) {

}

@Override
public void setPKeyAuthStatus(boolean status) {
return;
}
},
new OnPageLoadedCallback() {
@Override
public void onPageLoaded(final String url) {
return;
}
},
TEST_REDIRECT_URI,
Mockito.mock(SwitchBrowserRequestHandler.class));
mWebViewClient.shouldOverrideUrlLoading(mMockWebView, TEST_PASSKEY_REDIRECT_URL);
} catch (ClassCastException e) {
Assert.fail("Failure is not expected. The class checks should have prevented this." + e);
} catch (Exception e) {
Assert.fail("Failure is not expected." + e);
}
}
}