Skip to content

Petterh/issue 726: Do not treat web view errors as "cancel" #1018

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

Merged
merged 18 commits into from
Sep 6, 2019
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import android.webkit.SslErrorHandler;
import android.webkit.WebView;

import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
Expand Down Expand Up @@ -103,7 +104,7 @@ public void sendResponse(int returnCode, Intent responseIntent) {
}

@Override
public void cancelWebViewRequest() {
public void cancelWebViewRequest(@Nullable Intent errorIntent) {
// Do nothing. Test Object.
}

Expand Down Expand Up @@ -201,7 +202,7 @@ public void sendResponse(int returnCode, Intent responseIntent) {
}

@Override
public void cancelWebViewRequest() {
public void cancelWebViewRequest(@Nullable Intent errorIntent) {
countDownLatch.countDown();
}

Expand Down Expand Up @@ -276,7 +277,7 @@ public void sendResponse(int returnCode, Intent responseIntent) {
}

@Override
public void cancelWebViewRequest() {
public void cancelWebViewRequest(@Nullable Intent errorIntent) {
// Not under test
}

Expand Down Expand Up @@ -356,7 +357,7 @@ public void sendResponse(int returnCode, Intent responseIntent) {
}

@Override
public void cancelWebViewRequest() {
public void cancelWebViewRequest(@Nullable Intent errorIntent) {
// Not under test
}

Expand Down Expand Up @@ -437,7 +438,7 @@ public void sendResponse(int returnCode, Intent responseIntent) {
}

@Override
public void cancelWebViewRequest() {
public void cancelWebViewRequest(@Nullable Intent errorIntent) {
// Not under test
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import android.webkit.CookieSyncManager;
import android.webkit.WebView;

import androidx.annotation.Nullable;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.google.gson.Gson;
Expand Down Expand Up @@ -111,7 +112,6 @@
import static com.microsoft.aad.adal.AuthenticationConstants.Browser.WEBVIEW_INVALID_REQUEST;
import static com.microsoft.aad.adal.AuthenticationConstants.ENCODING_UTF8;
import static com.microsoft.aad.adal.AuthenticationConstants.UIResponse.BROKER_REQUEST_RESUME;
import static com.microsoft.aad.adal.AuthenticationConstants.UIResponse.BROWSER_CODE_CANCEL;
import static com.microsoft.aad.adal.AuthenticationConstants.UIResponse.BROWSER_CODE_COMPLETE;
import static com.microsoft.aad.adal.AuthenticationConstants.UIResponse.BROWSER_CODE_ERROR;
import static com.microsoft.aad.adal.AuthenticationConstants.UIResponse.TOKEN_BROKER_RESPONSE;
Expand Down Expand Up @@ -703,23 +703,29 @@ public void onBackPressed() {
// happen.
if (mPkeyAuthRedirect || !mWebView.canGoBackOrForward(BACK_PRESSED_CANCEL_DIALOG_STEPS)) {
// counting blank page as well
cancelRequest();
cancelRequest(null);
} else {
// Don't use default back pressed action, since user can go back in
// webview
mWebView.goBack();
}
}

private void cancelRequest() {
private void cancelRequest(@Nullable Intent errorIntent) {
Logger.verbose(TAG, "Sending intent to cancel authentication activity");
final Intent resultIntent = new Intent();

if (mUIEvent != null) {
mUIEvent.setUserCancel();
int resultCode;
Intent resultIntent = errorIntent;
if (resultIntent == null) {
resultIntent = new Intent();
resultCode = AuthenticationConstants.UIResponse.BROWSER_CODE_CANCEL;
if (mUIEvent != null) {
mUIEvent.setUserCancel();
}
} else {
resultCode = AuthenticationConstants.UIResponse.BROWSER_CODE_ERROR;
}

returnToCaller(BROWSER_CODE_CANCEL, resultIntent);
returnToCaller(resultCode, resultIntent);
}

private void prepareForBrokerResume() {
Expand Down Expand Up @@ -754,7 +760,7 @@ protected void onDestroy() {
}
}

class CustomWebViewClient extends BasicWebViewClient {
private class CustomWebViewClient extends BasicWebViewClient {

CustomWebViewClient() {
super(AuthenticationActivity.this, mRedirectUrl, mAuthRequest, mUIEvent);
Expand Down Expand Up @@ -854,8 +860,8 @@ public void sendResponse(final int returnCode, final Intent responseIntent) {
}

@Override
public void cancelWebViewRequest() {
cancelRequest();
public void cancelWebViewRequest(@Nullable Intent errorIntent) {
cancelRequest(errorIntent);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -841,4 +841,4 @@ static final class MediaType {
*/
static final String APPLICATION_JSON = com.microsoft.identity.common.adal.internal.AuthenticationConstants.MediaType.APPLICATION_JSON;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Handler;
import android.util.Log;
import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.webkit.WebView;
import android.widget.ProgressBar;

import androidx.annotation.Nullable;

import com.microsoft.identity.common.adal.internal.AuthenticationConstants;

import java.io.UnsupportedEncodingException;
Expand Down Expand Up @@ -167,7 +168,7 @@ public boolean onTouch(View view, MotionEvent event) {
mWebView.post(new Runnable() {
@Override
public void run() {
mWebView.loadUrl("about:blank");
mWebView.loadUrl(BasicWebViewClient.BLANK_PAGE);
mWebView.loadUrl(startUrl);
}
});
Expand All @@ -181,7 +182,7 @@ public void run() {

@Override
public void onCancel(DialogInterface dialog) {
cancelFlow();
cancelFlow(null);
}
});
mDialog = builder.create();
Expand All @@ -191,12 +192,21 @@ public void onCancel(DialogInterface dialog) {
});
}

private void cancelFlow() {
private void cancelFlow(@Nullable Intent errorIntent) {
Logger.i(TAG, "Cancelling dialog", "");
Intent resultIntent = new Intent();
Intent resultIntent = errorIntent;
int resultCode;
if (resultIntent == null) {
resultIntent = new Intent();
resultCode = AuthenticationConstants.UIResponse.BROWSER_CODE_CANCEL;
} else {
resultCode = AuthenticationConstants.UIResponse.BROWSER_CODE_ERROR;
}

resultIntent.putExtra(AuthenticationConstants.Browser.REQUEST_ID, mRequest.getRequestId());

mAcquireTokenRequest.onActivityResult(AuthenticationConstants.UIRequest.BROWSER_FLOW,
AuthenticationConstants.UIResponse.BROWSER_CODE_CANCEL, resultIntent);
resultCode, resultIntent);
if (mHandlerInView != null) {
mHandlerInView.post(new Runnable() {
@Override
Expand Down Expand Up @@ -258,8 +268,8 @@ public void processRedirectUrl(final WebView view, String url) {
}

@Override
public void cancelWebViewRequest() {
cancelFlow();
public void cancelWebViewRequest(@Nullable Intent errorIntent) {
cancelFlow(errorIntent);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

package com.microsoft.aad.adal;

import androidx.annotation.Nullable;

import com.microsoft.identity.common.adal.internal.util.StringExtensions;

import org.json.JSONArray;
Expand All @@ -41,7 +43,6 @@
/**
* Hold the authority validation metadata.
*/

final class AuthorityValidationMetadataCache {
private static final String TAG = AuthorityValidationMetadataCache.class.getSimpleName();

Expand All @@ -66,9 +67,11 @@ static boolean containsAuthorityHost(final URL authorityUrl) {
}

static boolean isAuthorityValidated(final URL authorityUrl) {
return containsAuthorityHost(authorityUrl) && getCachedInstanceDiscoveryMetadata(authorityUrl).isValidated();
InstanceDiscoveryMetadata discoveryMetadata = getCachedInstanceDiscoveryMetadata(authorityUrl);
return containsAuthorityHost(authorityUrl) && discoveryMetadata != null && discoveryMetadata.isValidated();
}

@Nullable
static InstanceDiscoveryMetadata getCachedInstanceDiscoveryMetadata(final URL authorityUrl) {
return sAadAuthorityHostMetadata.get(authorityUrl.getHost().toLowerCase(Locale.US));
}
Expand Down Expand Up @@ -129,4 +132,4 @@ private static InstanceDiscoveryMetadata processSingleJsonArray(final JSONObject

return new InstanceDiscoveryMetadata(preferredNetwork, preferredCache, aliases);
}
}
}
28 changes: 17 additions & 11 deletions adal/src/main/java/com/microsoft/aad/adal/BasicWebViewClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ abstract class BasicWebViewClient extends WebViewClient {
private static final String INSTALL_URL_KEY = "app_link";
private static final String TAG = "BasicWebViewClient";

private static final String BLANK_PAGE = "about:blank";
static final String BLANK_PAGE = "about:blank";

final AuthenticationRequest mRequest;

Expand All @@ -87,7 +87,7 @@ abstract class BasicWebViewClient extends WebViewClient {

public abstract void sendResponse(int returnCode, Intent responseIntent);

public abstract void cancelWebViewRequest();
public abstract void cancelWebViewRequest(@Nullable Intent errorIntent);

public abstract void prepareForBrokerResumeRequest();

Expand Down Expand Up @@ -136,7 +136,7 @@ public void onCancel() {
);

handler.cancel();
cancelWebViewRequest();
cancelWebViewRequest(null);
}
});

Expand Down Expand Up @@ -396,15 +396,16 @@ public void run() {
"Navigation starts with the redirect uri."
);

if (hasCancelError(url)) {
Intent errorIntent = parseError(url);
if (errorIntent != null) {
// Catch WEB-UI cancel request
com.microsoft.identity.common.internal.logging.Logger.info(
TAG + methodName,
"Sending intent to cancel authentication activity"
);

view.stopLoading();
cancelWebViewRequest();
cancelWebViewRequest(errorIntent);
return true;
}

Expand All @@ -418,7 +419,7 @@ public void run() {

openLinkInBrowser(url);
view.stopLoading();
cancelWebViewRequest();
cancelWebViewRequest(null);
return true;
} else if (url.startsWith(BROWSER_EXT_INSTALL_PREFIX)) {
com.microsoft.identity.common.internal.logging.Logger.verbose(
Expand Down Expand Up @@ -465,10 +466,10 @@ protected void openLinkInBrowser(final String url) {
mCallingContext.startActivity(intent);
}

protected boolean hasCancelError(final String redirectUrl) {
private Intent parseError(String redirectUrl) {
final Map<String, String> parameters = StringExtensions.getUrlParameters(redirectUrl);
final String error = parameters.get("error");
final String errorDescription = parameters.get("error_description");
final String error = parameters.get(AuthenticationConstants.OAuth2.ERROR);
final String errorDescription = parameters.get(AuthenticationConstants.OAuth2.ERROR_DESCRIPTION);

if (!StringExtensions.isNullOrBlank(error)) {
com.microsoft.identity.common.internal.logging.Logger.warnPII(
Expand All @@ -478,9 +479,14 @@ protected boolean hasCancelError(final String redirectUrl) {
+ "Error Description: " + errorDescription
);

return true;
Intent intent = new Intent();
intent.putExtra(AuthenticationConstants.OAuth2.ERROR, error);
intent.putExtra(AuthenticationConstants.Browser.RESPONSE_ERROR_CODE, error);
intent.putExtra(AuthenticationConstants.OAuth2.ERROR_DESCRIPTION, errorDescription);
intent.putExtra(AuthenticationConstants.Browser.RESPONSE_ERROR_MESSAGE, errorDescription);
return intent;
}

return false;
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public enum PromptBehavior {
* If Azure Authenticator or Company Portal is installed, this flag will have
* the broker app force the prompt behavior, otherwise it will be same as Always.
* If using embedded flow, please keep using Always, if FORCE_PROMPT is set for
* embedded flow, the sdk will re-intepret it to Always.
* embedded flow, the sdk will re-interpret it to Always.
*/
FORCE_PROMPT
}