Skip to content

Commit dc33950

Browse files
authored
Take flight value for whether to show webcp flow in weview or not in brokerless scenarios. Fixes AB#3407952 (#2784)
1. In brokerless scenarios, we cannot control flighting the features. 2. WebCp in webview feature is planned to be first rolled out in brokered scenarios using flighting (slowing going from 25 to 100% in 4 weeks) 3. Once we complete step 2 above, we want to enable the feature by default in brokerless scenarios as well. 4. But in case there are any issues found, we also want to be able to provide a kill switch to calling apps to turn the feature off. 5. This PR takes a boolean value from OneAuth to decide whether to show webcp in webview or not. 6. Changes are made in OneAuth side as well for passing the value. Fixes [AB#3407952](https://identitydivision.visualstudio.com/fac9d424-53d2-45c0-91b5-ef6ba7a6bf26/_workitems/edit/3407952)
1 parent 0b88339 commit dc33950

File tree

7 files changed

+83
-14
lines changed

7 files changed

+83
-14
lines changed

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ vNext
1313
- [PATCH] Fix for app link redirect from CCT due to forced browser preference (#2775)
1414
- [MINOR] getAllSsoTokens method for Edge (#2774)
1515
- [MINOR] WebApps AccountId Registry (#2787)
16+
- [MINOR] Take flight value for whether to show webcp flow in weview or not in brokerless scenarios. (#2784)
1617

1718
Version 22.1.3
1819
----------

common/src/main/java/com/microsoft/identity/common/adal/internal/AuthenticationConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2054,6 +2054,8 @@ public static final class AuthorizationIntentKey {
20542054

20552055
public static final String WEB_VIEW_ZOOM_ENABLED = "com.microsoft.identity.web.view.zoom.enabled";
20562056

2057+
public static final String WEB_VIEW_WEB_CP_ENABLED = "com.microsoft.identity.web.view.web.cp.enabled";
2058+
20572059
public static final String OTEL_CONTEXT_CARRIER = "otel_context_carrier";
20582060

20592061
public static final String WEB_VIEW_SILENT_AUTHORIZATION_FLOW_TIMEOUT = "com.microsoft.identity.web.view.silent.authorization.flow.timeout";

common/src/main/java/com/microsoft/identity/common/internal/providers/oauth2/AuthorizationActivityFactory.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ object AuthorizationActivityFactory {
110110
AuthenticationConstants.AuthorizationIntentKey.WEB_VIEW_ZOOM_ENABLED,
111111
parameters.webViewZoomEnabled
112112
)
113+
putExtra(
114+
AuthenticationConstants.AuthorizationIntentKey.WEB_VIEW_WEB_CP_ENABLED,
115+
parameters.isWebViewWebCpEnabled
116+
)
113117
putExtra(
114118
DiagnosticContext.CORRELATION_ID,
115119
DiagnosticContext.INSTANCE.requestContext[DiagnosticContext.CORRELATION_ID]

common/src/main/java/com/microsoft/identity/common/internal/providers/oauth2/AuthorizationActivityParameters.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import com.microsoft.identity.common.java.ui.AuthorizationAgent
4141
* @param sourceLibraryVersion Product version to be of library making the request
4242
* @param utid The tenant unique id, if applicable
4343
* @param webViewEnableSilentAuthorizationFlowTimeOutMs If set to a non-null value, this indicates that the flow is silent and specifies the timeout for the silent authorization flow in milliseconds.
44+
* @param isWebViewWebCpEnabled This parameter controls whether webcp URLs should be handled within the WebView or redirected to external browser
4445
*/
4546
data class AuthorizationActivityParameters @JvmOverloads constructor(
4647
val context: Context,
@@ -57,5 +58,6 @@ data class AuthorizationActivityParameters @JvmOverloads constructor(
5758
* The tenant unique id
5859
*/
5960
val utid: String? = null,
60-
val webViewEnableSilentAuthorizationFlowTimeOutMs: Long? = null
61+
val webViewEnableSilentAuthorizationFlowTimeOutMs: Long? = null,
62+
val isWebViewWebCpEnabled: Boolean = false,
6163
)

common/src/main/java/com/microsoft/identity/common/internal/providers/oauth2/WebViewAuthorizationFragment.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import static com.microsoft.identity.common.adal.internal.AuthenticationConstants.AuthorizationIntentKey.REQUEST_URL;
3030
import static com.microsoft.identity.common.adal.internal.AuthenticationConstants.AuthorizationIntentKey.WEB_VIEW_ZOOM_CONTROLS_ENABLED;
3131
import static com.microsoft.identity.common.adal.internal.AuthenticationConstants.AuthorizationIntentKey.WEB_VIEW_ZOOM_ENABLED;
32+
import static com.microsoft.identity.common.adal.internal.AuthenticationConstants.AuthorizationIntentKey.WEB_VIEW_WEB_CP_ENABLED;
3233
import static com.microsoft.identity.common.java.AuthenticationConstants.SdkPlatformFields.PRODUCT;
3334
import static com.microsoft.identity.common.java.AuthenticationConstants.SdkPlatformFields.VERSION;
3435

@@ -117,6 +118,8 @@ public class WebViewAuthorizationFragment extends AuthorizationFragment {
117118

118119
private boolean webViewZoomEnabled;
119120

121+
private boolean isWebViewWebcpEnabledInBrokerlessCase;
122+
120123
private String mUtid;
121124

122125
private final CameraPermissionRequestHandler mCameraPermissionRequestHandler = new CameraPermissionRequestHandler(this);
@@ -201,6 +204,7 @@ public void onSaveInstanceState(@NonNull Bundle outState) {
201204
outState.putSerializable(POST_PAGE_LOADED_URL, mPostPageLoadedJavascript);
202205
outState.putBoolean(WEB_VIEW_ZOOM_CONTROLS_ENABLED, webViewZoomControlsEnabled);
203206
outState.putBoolean(WEB_VIEW_ZOOM_ENABLED, webViewZoomEnabled);
207+
outState.putBoolean(WEB_VIEW_WEB_CP_ENABLED, isWebViewWebcpEnabledInBrokerlessCase);
204208
outState.putString(UTID, mUtid);
205209
}
206210

@@ -219,6 +223,7 @@ void extractState(@NonNull final Bundle state) {
219223
mPostPageLoadedJavascript = state.getString(POST_PAGE_LOADED_URL);
220224
webViewZoomEnabled = state.getBoolean(WEB_VIEW_ZOOM_ENABLED, true);
221225
webViewZoomControlsEnabled = state.getBoolean(WEB_VIEW_ZOOM_CONTROLS_ENABLED, true);
226+
isWebViewWebcpEnabledInBrokerlessCase = state.getBoolean(WEB_VIEW_WEB_CP_ENABLED, false);
222227
mUtid = state.getString(UTID);
223228
}
224229

@@ -258,7 +263,8 @@ public void onPageLoaded(final String url) {
258263
},
259264
mRedirectUri,
260265
getSwitchBrowserCoordinator().getSwitchBrowserRequestHandler(),
261-
mUtid
266+
mUtid,
267+
isWebViewWebcpEnabledInBrokerlessCase
262268
);
263269
setUpWebView(view, mAADWebViewClient);
264270
mAADWebViewClient.initializeAuthUxJavaScriptApi(mWebView, mAuthorizationRequestUrl);

common/src/main/java/com/microsoft/identity/common/internal/ui/webview/AzureActiveDirectoryWebViewClient.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ public class AzureActiveDirectoryWebViewClient extends OAuth2WebViewClient {
135135
private HashMap<String, String> mRequestHeaders;
136136
private String mRequestUrl;
137137
private boolean mInWebCpFlow = false;
138+
private boolean mAuthUxJavaScriptInterfaceAdded = false;
139+
// Determines whether to handle WebCP requests in the WebView in brokerless scenarios.
140+
private final boolean mIsWebViewWebCpEnabledInBrokerlessCase;
141+
138142

139143
private final String mUtid;
140144

@@ -143,12 +147,14 @@ public AzureActiveDirectoryWebViewClient(@NonNull final Activity activity,
143147
@NonNull final OnPageLoadedCallback pageLoadedCallback,
144148
@NonNull final String redirectUrl,
145149
@NonNull final SwitchBrowserRequestHandler switchBrowserRequestHandler,
146-
@Nullable final String utid) {
150+
@Nullable final String utid,
151+
final boolean isWebViewWebCpEnabledInBrokerlessCase) {
147152
super(activity, completionCallback, pageLoadedCallback);
148153
mRedirectUrl = redirectUrl;
149154
mCertBasedAuthFactory = new CertBasedAuthFactory(activity);
150155
mSwitchBrowserRequestHandler = switchBrowserRequestHandler;
151156
mUtid = utid;
157+
mIsWebViewWebCpEnabledInBrokerlessCase = isWebViewWebCpEnabledInBrokerlessCase;
152158
}
153159

154160
/**
@@ -704,9 +710,9 @@ protected boolean isWebCpInWebviewFeatureEnabled(@NonNull final String originalU
704710
final String methodTag = TAG + ":isWebCpInWebviewFeatureEnabled";
705711
try {
706712
if (!ProcessUtil.isRunningOnAuthService(getActivity().getApplicationContext())) {
707-
// Enabling webcp in webview feature for brokered flows only for now.
708-
Logger.info(methodTag, "Not running on AuthService, skipping WebCP in WebView feature check.");
709-
return false;
713+
mInWebCpFlow = mIsWebViewWebCpEnabledInBrokerlessCase;
714+
Logger.info(methodTag, "Not running on AuthService, WebCP in WebView feature enabled? "+ mIsWebViewWebCpEnabledInBrokerlessCase);
715+
return mInWebCpFlow;
710716
}
711717

712718
final String homeTenantId = !StringUtil.isNullOrEmpty(mUtid)? mUtid : getHomeTenantIdFromUrl(originalUrl);

common/src/test/java/com/microsoft/identity/common/internal/ui/webview/AzureActiveDirectoryWebViewClientTest.java

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,8 @@ public void onPageLoaded(final String url) {
148148
},
149149
TEST_REDIRECT_URI,
150150
Mockito.mock(SwitchBrowserRequestHandler.class),
151-
"homeTenantId");
151+
"homeTenantId",
152+
false);
152153
HashMap<String, String> dummyHeaders = new HashMap<>();
153154
dummyHeaders.put("key", "value");
154155
mWebViewClient.setRequestHeaders(dummyHeaders);
@@ -373,6 +374,46 @@ public void testLoadDeviceCaUrlInBrowserInBrokelessFlow() {
373374
Mockito.verify(mockWebview, Mockito.never()).loadUrl(Mockito.anyString(), Mockito.any());
374375
}
375376

377+
@Test
378+
public void testLoadDeviceCaUrlInWebviewInBrokelessFlow() {
379+
// Mocks
380+
final WebView mockWebview = Mockito.mock(WebView.class);
381+
final AzureActiveDirectoryWebViewClient mockWebViewClient = new AzureActiveDirectoryWebViewClient(
382+
mActivity,
383+
new IAuthorizationCompletionCallback() {
384+
@Override
385+
public void onChallengeResponseReceived(@NonNull RawAuthorizationResult response) {
386+
387+
}
388+
389+
@Override
390+
public void setPKeyAuthStatus(boolean status) {
391+
return;
392+
}
393+
},
394+
new OnPageLoadedCallback() {
395+
@Override
396+
public void onPageLoaded(final String url) {
397+
return;
398+
}
399+
},
400+
TEST_REDIRECT_URI,
401+
Mockito.mock(SwitchBrowserRequestHandler.class),
402+
"homeTenantId",
403+
true);
404+
final IFlightsProvider mockFlightsProvider = Mockito.mock(IFlightsProvider.class);
405+
when(mockFlightsProvider.isFlightEnabled(CommonFlight.ENABLE_WEB_CP_IN_WEBVIEW)).thenReturn(true);
406+
407+
final MockCommonFlightsManager mockCommonFlightsManager = new MockCommonFlightsManager();
408+
mockCommonFlightsManager.setMockCommonFlightsProvider(mockFlightsProvider);
409+
CommonFlightsManager.INSTANCE.initializeCommonFlightsManager(mockCommonFlightsManager);
410+
// Actual call
411+
mockWebViewClient.loadDeviceCaUrl(TEST_BROWSER_DEVICE_CA_URL_QUERY_STRING_PARAMETER, mockWebview);
412+
// Verify
413+
Mockito.verify(mockFlightsProvider, Mockito.never()).isFlightEnabled(Mockito.any());
414+
Mockito.verify(mockWebview).loadUrl(Mockito.anyString(), Mockito.any());
415+
}
416+
376417
@Test
377418
public void testProcessCloudRedirectAndPrtHeaderInternalSuccess() {
378419
ReAttachPrtHeaderHandler mockCrossCloudChallengeHandler = Mockito.mock(ReAttachPrtHeaderHandler.class);
@@ -431,7 +472,8 @@ public void onPageLoaded(final String url) {
431472
},
432473
TEST_REDIRECT_URI,
433474
Mockito.mock(SwitchBrowserRequestHandler.class),
434-
"homeTenantId");
475+
"homeTenantId",
476+
false);
435477
mWebViewClient.shouldOverrideUrlLoading(mMockWebView, TEST_PASSKEY_REDIRECT_URL);
436478
} catch (ClassCastException e) {
437479
Assert.fail("Failure is not expected. The class checks should have prevented this." + e);
@@ -453,7 +495,8 @@ public void testOnReceivedSslError_Legacy() {
453495
url -> {},
454496
TEST_REDIRECT_URI,
455497
Mockito.mock(SwitchBrowserRequestHandler.class),
456-
"homeTenantId");
498+
"homeTenantId",
499+
false);
457500
final WebView mockWebView = new WebView(mContext);
458501
mockWebView.setWebViewClient(mockWebViewClient);
459502

@@ -481,7 +524,8 @@ public void testOnReceivedSslError() {
481524
url -> {},
482525
TEST_REDIRECT_URI,
483526
Mockito.mock(SwitchBrowserRequestHandler.class),
484-
"homeTenantId"
527+
"homeTenantId",
528+
false
485529
);
486530
final WebView mockWebView = new WebView(mContext);
487531
mockWebView.setWebViewClient(mockWebViewClient);
@@ -522,7 +566,8 @@ private void testProcessWebsiteRequest_BrowserRedirect() {
522566
url -> {},
523567
TEST_REDIRECT_URI,
524568
Mockito.mock(SwitchBrowserRequestHandler.class),
525-
"homeTenantId"
569+
"homeTenantId",
570+
false
526571
));
527572
final WebView mockWebView = Mockito.mock(WebView.class);
528573

@@ -549,7 +594,8 @@ private void testProcessWebsiteRequest_DeviceCaRequest() {
549594
url -> {},
550595
TEST_REDIRECT_URI,
551596
Mockito.mock(SwitchBrowserRequestHandler.class),
552-
"homeTenantId"
597+
"homeTenantId",
598+
false
553599
));
554600
final WebView mockWebView = Mockito.mock(WebView.class);
555601

@@ -581,7 +627,8 @@ private void testProcessWebsiteRequest_WebCpPlaystoreRedirect() {
581627
url -> {},
582628
TEST_REDIRECT_URI,
583629
Mockito.mock(SwitchBrowserRequestHandler.class),
584-
"homeTenantId"
630+
"homeTenantId",
631+
false
585632
);
586633
final WebView mockWebView = Mockito.mock(WebView.class);
587634

@@ -620,7 +667,8 @@ private void testProcessWebsiteRequest_ExceptionHandling() {
620667
url -> {},
621668
TEST_REDIRECT_URI,
622669
Mockito.mock(SwitchBrowserRequestHandler.class),
623-
"homeTenantId"
670+
"homeTenantId",
671+
false
624672
));
625673
final WebView mockWebView = Mockito.mock(WebView.class);
626674

0 commit comments

Comments
 (0)