正在查看: St.John's v1.0.9 应用的 AzureActiveDirectoryWebViewClient.java JAVA 源代码文件
本页面展示 JAVA 反编译生成的源代码文件,支持语法高亮显示。 仅供安全研究与技术分析使用,严禁用于任何非法用途。请遵守相关法律法规。
正在查看: St.John's v1.0.9 应用的 AzureActiveDirectoryWebViewClient.java JAVA 源代码文件
本页面展示 JAVA 反编译生成的源代码文件,支持语法高亮显示。 仅供安全研究与技术分析使用,严禁用于任何非法用途。请遵守相关法律法规。
package com.microsoft.identity.common.internal.ui.webview;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.webkit.ClientCertRequest;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import com.microsoft.identity.common.adal.internal.AuthenticationConstants;
import com.microsoft.identity.common.adal.internal.util.StringExtensions;
import com.microsoft.identity.common.internal.broker.PackageHelper;
import com.microsoft.identity.common.internal.ui.webview.certbasedauth.AbstractCertBasedAuthChallengeHandler;
import com.microsoft.identity.common.internal.ui.webview.certbasedauth.AbstractSmartcardCertBasedAuthChallengeHandler;
import com.microsoft.identity.common.internal.ui.webview.certbasedauth.CertBasedAuthFactory;
import com.microsoft.identity.common.internal.ui.webview.challengehandlers.PKeyAuthChallengeHandler;
import com.microsoft.identity.common.java.AuthenticationConstants;
import com.microsoft.identity.common.java.challengehandlers.PKeyAuthChallengeFactory;
import com.microsoft.identity.common.java.constants.FidoConstants;
import com.microsoft.identity.common.java.exception.ClientException;
import com.microsoft.identity.common.java.exception.ErrorStrings;
import com.microsoft.identity.common.java.providers.RawAuthorizationResult;
import com.microsoft.identity.common.java.ui.webview.authorization.IAuthorizationCompletionCallback;
import com.microsoft.identity.common.java.util.StringUtil;
import com.microsoft.identity.common.logging.Logger;
import java.net.URISyntaxException;
import java.security.Principal;
import java.util.HashMap;
import java.util.Locale;
public class AzureActiveDirectoryWebViewClient extends OAuth2WebViewClient {
private static final String DEVICE_CERT_ISSUER = "CN=MS-Organization-Access";
public static final String ERROR = "error";
public static final String ERROR_DESCRIPTION = "error_description";
public static final String ERROR_SUBCODE = "error_subcode";
private static final String TAG = "AzureActiveDirectoryWebViewClient";
private AbstractCertBasedAuthChallengeHandler mCertBasedAuthChallengeHandler;
private final CertBasedAuthFactory mCertBasedAuthFactory;
private final String mRedirectUrl;
private HashMap<String, String> mRequestHeaders;
public AzureActiveDirectoryWebViewClient(Activity activity, IAuthorizationCompletionCallback iAuthorizationCompletionCallback, OnPageLoadedCallback onPageLoadedCallback, String str) {
super(activity, iAuthorizationCompletionCallback, onPageLoadedCallback);
this.mRedirectUrl = str;
this.mCertBasedAuthFactory = new CertBasedAuthFactory(activity);
}
@Override
public boolean shouldOverrideUrlLoading(WebView webView, String str) {
if (StringUtil.isNullOrEmpty(str)) {
throw new IllegalArgumentException("Redirect to empty url in web view.");
}
return handleUrl(webView, str);
}
@Override
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest webResourceRequest) {
return handleUrl(webView, webResourceRequest.getUrl().toString());
}
public void setRequestHeaders(HashMap<String, String> hashMap) {
this.mRequestHeaders = hashMap;
}
private boolean handleUrl(WebView webView, String str) {
String str2 = TAG + ":handleUrl";
String lowerCase = str.toLowerCase(Locale.US);
try {
if (isPkeyAuthUrl(lowerCase)) {
Logger.info(str2, "WebView detected request for pkeyauth challenge.");
new PKeyAuthChallengeHandler(webView, getCompletionCallback()).processChallenge(new PKeyAuthChallengeFactory().getPKeyAuthChallengeFromWebViewRedirect(str));
return true;
}
if (isRedirectUrl(lowerCase)) {
Logger.info(str2, "Navigation starts with the redirect uri.");
processRedirectUrl(webView, str);
return true;
}
if (isWebsiteRequestUrl(lowerCase)) {
Logger.info(str2, "It is an external website request");
processWebsiteRequest(webView, str);
return true;
}
if (isInstallRequestUrl(lowerCase)) {
Logger.info(str2, "It is an install request");
processInstallRequest(webView, str);
return true;
}
if (isWebCpUrl(lowerCase)) {
Logger.info(str2, "It is a request from WebCP");
processWebCpRequest(webView, str);
return true;
}
if (isPlayStoreUrl(lowerCase)) {
Logger.info(str2, "Request to open PlayStore.");
return processPlayStoreURL(webView, str);
}
if (isAuthAppMFAUrl(lowerCase)) {
Logger.info(str2, "Request to link account with Authenticator.");
processAuthAppMFAUrl(str);
return true;
}
if (isAmazonAppRedirect(lowerCase)) {
Logger.info(str2, "It is an Amazon app request");
processAmazonAppUri(str);
return true;
}
if (isInvalidRedirectUri(str)) {
Logger.info(str2, "Check for Redirect Uri.");
processInvalidRedirectUri(webView, str);
return true;
}
if (isBlankPageRequest(lowerCase)) {
Logger.info(str2, "It is an blank page request");
return true;
}
if (!isUriSSLProtected(lowerCase)) {
Logger.info(str2, "Check for SSL protection");
processSSLProtectionCheck(webView, str);
return true;
}
if (isHeaderForwardingRequiredUri(str)) {
processHeaderForwardingRequiredUri(webView, str);
return true;
}
Logger.info(str2, "This maybe a valid URI, but no special handling for this mentioned URI, hence deferring to WebView for loading.");
processInvalidUrl(str);
return false;
} catch (ClientException e) {
Logger.error(str2, e.getErrorCode(), null);
Logger.errorPII(str2, e.getMessage(), e);
returnError(e.getErrorCode(), e.getMessage());
webView.stopLoading();
return true;
}
}
private boolean isUriSSLProtected(String str) {
return str.startsWith(AuthenticationConstants.Broker.REDIRECT_SSL_PREFIX);
}
private boolean isBlankPageRequest(String str) {
return "about:blank".equals(str);
}
private boolean isInvalidRedirectUri(String str) {
return isBrokerRequest(getActivity().getIntent()) && str.startsWith("msauth");
}
private boolean isAuthAppMFAUrl(String str) {
return str.startsWith(AuthenticationConstants.Broker.AUTHENTICATOR_MFA_LINKING_PREFIX);
}
private boolean isPlayStoreUrl(String str) {
return str.startsWith(AuthenticationConstants.Broker.PLAY_STORE_INSTALL_PREFIX);
}
private boolean isPkeyAuthUrl(String str) {
return str.startsWith(AuthenticationConstants.Broker.PKEYAUTH_REDIRECT.toLowerCase(Locale.ROOT));
}
private boolean isPasskeyUrl(String str) {
return str.startsWith(FidoConstants.PASSKEY_PROTOCOL_REDIRECT.toLowerCase(Locale.ROOT));
}
private boolean isRedirectUrl(String str) {
return str.startsWith(this.mRedirectUrl.toLowerCase(Locale.US));
}
private boolean isWebsiteRequestUrl(String str) {
return str.startsWith(AuthenticationConstants.Broker.BROWSER_EXT_PREFIX);
}
private boolean isInstallRequestUrl(String str) {
return str.startsWith(AuthenticationConstants.Broker.BROWSER_EXT_INSTALL_PREFIX);
}
private boolean isBrokerRequest(Intent intent) {
return (intent == null || StringExtensions.isNullOrBlank(intent.getStringExtra(AuthenticationConstants.Broker.BROKER_REQUEST))) ? false : true;
}
private boolean isWebCpUrl(String str) {
return str.startsWith(AuthenticationConstants.Broker.BROWSER_EXT_WEB_CP);
}
private boolean isAmazonAppRedirect(String str) {
return str.startsWith(AuthenticationConstants.Broker.AMAZON_APP_REDIRECT_PREFIX);
}
private boolean isHeaderForwardingRequiredUri(String str) {
boolean startsWith = str.startsWith("https://login.live.com/");
HashMap<String, String> hashMap = this.mRequestHeaders;
return startsWith && (hashMap != null && !hashMap.isEmpty());
}
protected void processRedirectUrl(WebView webView, String str) {
Logger.info(TAG + ":processRedirectUrl", "It is pointing to redirect. Final url can be processed to get the code or error.");
getCompletionCallback().onChallengeResponseReceived(RawAuthorizationResult.fromRedirectUri(str));
webView.stopLoading();
}
private void processWebsiteRequest(WebView webView, String str) {
String str2 = TAG + ":processWebsiteRequest";
webView.stopLoading();
if (str.contains(AuthenticationConstants.Broker.BROWSER_DEVICE_CA_URL_QUERY_STRING_PARAMETER)) {
Logger.info(str2, "This is a device CA request.");
PackageHelper packageHelper = new PackageHelper(getActivity().getPackageManager());
if (packageHelper.isPackageInstalledAndEnabled(AuthenticationConstants.Broker.IPPHONE_APP_PACKAGE_NAME) && AuthenticationConstants.Broker.IPPHONE_APP_SIGNATURE.equals(packageHelper.getSha1SignatureForPackage(AuthenticationConstants.Broker.IPPHONE_APP_PACKAGE_NAME)) && packageHelper.isPackageInstalledAndEnabled(AuthenticationConstants.Broker.COMPANY_PORTAL_APP_PACKAGE_NAME)) {
try {
launchCompanyPortal();
return;
} catch (Exception unused) {
Logger.warn(str2, "Failed to launch Company Portal, falling back to browser.");
}
}
openLinkInBrowser(str);
returnResult(RawAuthorizationResult.ResultCode.MDM_FLOW);
return;
}
openLinkInBrowser(str);
returnResult(RawAuthorizationResult.ResultCode.CANCELLED);
}
private boolean processPlayStoreURL(WebView webView, String str) {
String str2 = TAG + ":processPlayStoreURL";
webView.stopLoading();
if (!str.startsWith("market://details?id=com.microsoft.windowsintune.companyportal") && !str.startsWith("market://details?id=com.azure.authenticator")) {
Logger.info(str2, "The URI is either trying to open an unknown application or contains unknown query parameters");
return false;
}
String str3 = AuthenticationConstants.Broker.COMPANY_PORTAL_APP_PACKAGE_NAME;
if (!str.contains(AuthenticationConstants.Broker.COMPANY_PORTAL_APP_PACKAGE_NAME)) {
str3 = AuthenticationConstants.Broker.AZURE_AUTHENTICATOR_APP_PACKAGE_NAME;
}
Logger.info(str2, "Request to open PlayStore to install package : '" + str3 + "'");
try {
Intent intent = new Intent("android.intent.action.VIEW", Uri.parse(AuthenticationConstants.Broker.PLAY_STORE_INSTALL_PREFIX.concat(str3)));
intent.addFlags(268468224);
getActivity().startActivity(intent);
return true;
} catch (ActivityNotFoundException e) {
Logger.error(str2, "PlayStore is not present on the device", e);
return true;
}
}
private void processAuthAppMFAUrl(String str) {
String str2 = TAG + ":processAuthAppMFAUrl";
Logger.verbose(str2, "Linking Account in Broker for MFA.");
try {
Intent intent = new Intent("android.intent.action.VIEW", Uri.parse(str));
intent.addFlags(268435456);
getActivity().startActivity(intent);
} catch (ActivityNotFoundException e) {
Logger.error(str2, "Failed to open the Authenticator application.", e);
}
}
private void launchCompanyPortal() {
Logger.verbose(TAG + ":launchCompanyPortal", "Sending intent to launch the CompanyPortal.");
Intent intent = new Intent();
intent.setComponent(new ComponentName(AuthenticationConstants.Broker.COMPANY_PORTAL_APP_PACKAGE_NAME, AuthenticationConstants.Broker.COMPANY_PORTAL_APP_LAUNCH_ACTIVITY_NAME));
intent.addFlags(268468224);
getActivity().startActivity(intent);
returnResult(RawAuthorizationResult.ResultCode.MDM_FLOW);
}
private void processAmazonAppUri(String str) {
String str2 = TAG + ":processAmazonAppUri";
getActivity().startActivity(new Intent("android.intent.action.VIEW", Uri.parse(str)));
Logger.info(str2, "Sent Intent to launch Amazon app");
}
private void openLinkInBrowser(String str) {
String str2 = TAG + ":openLinkInBrowser";
Logger.info(str2, "Try to open url link in browser");
Intent intent = new Intent("android.intent.action.VIEW", Uri.parse(str.replace(AuthenticationConstants.Broker.BROWSER_EXT_PREFIX, AuthenticationConstants.Broker.REDIRECT_SSL_PREFIX)));
if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
getActivity().startActivity(intent);
} else {
Logger.warn(str2, "Unable to find an app to resolve the activity.");
}
}
private void processWebCpRequest(WebView webView, String str) {
webView.stopLoading();
if (str.equalsIgnoreCase(AuthenticationConstants.Broker.WEBCP_LAUNCH_COMPANY_PORTAL_URL)) {
launchCompanyPortal();
return;
}
returnError(ErrorStrings.WEBCP_URI_INVALID, "Unexpected URL from WebCP: " + str);
}
private void processInstallRequest(final WebView webView, String str) {
String str2 = TAG + ":processInstallRequest";
RawAuthorizationResult fromRedirectUri = RawAuthorizationResult.fromRedirectUri(str);
if (fromRedirectUri.getResultCode() != RawAuthorizationResult.ResultCode.BROKER_INSTALLATION_TRIGGERED) {
getCompletionCallback().onChallengeResponseReceived(fromRedirectUri);
webView.stopLoading();
return;
}
final String str3 = StringExtensions.getUrlParameters(str).get(AuthenticationConstants.AAD.APP_LINK_KEY);
Logger.info(str2, "Launching the link to app:" + str3);
getCompletionCallback().onChallengeResponseReceived(fromRedirectUri);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
AzureActiveDirectoryWebViewClient.this.getActivity().startActivity(new Intent("android.intent.action.VIEW", Uri.parse(str3.replace(AuthenticationConstants.Broker.BROWSER_EXT_PREFIX, AuthenticationConstants.Broker.REDIRECT_SSL_PREFIX))));
webView.stopLoading();
}
}, 1000L);
webView.stopLoading();
}
private void processInvalidRedirectUri(WebView webView, String str) {
String str2 = TAG + ":processInvalidRedirectUri";
Logger.error(str2, "The RedirectUri is not as expected.", null);
Logger.errorPII(str2, String.format("Received %s and expected %s", str, this.mRedirectUrl), null);
returnError(ErrorStrings.DEVELOPER_REDIRECTURI_INVALID, String.format("The RedirectUri is not as expected. Received %s and expected %s", str, this.mRedirectUrl));
webView.stopLoading();
}
private void processSSLProtectionCheck(WebView webView, String str) {
Logger.error(TAG + ":processSSLProtectionCheck", "The webView was redirected to an unsafe URL: " + removeQueryParametersOrRedact(str), null);
returnError(ErrorStrings.WEBVIEW_REDIRECTURL_NOT_SSL_PROTECTED, "The webView was redirected to an unsafe URL.");
webView.stopLoading();
}
private void processInvalidUrl(String str) {
Logger.infoPII(TAG + ":processInvalidUrl", "We are declining to override loading and redirect to invalid URL: '" + removeQueryParametersOrRedact(str) + "' the user's url pattern is '" + this.mRedirectUrl + "'");
}
private void processHeaderForwardingRequiredUri(WebView webView, String str) {
Logger.infoPII(TAG + ":processHeaderForwardingRequiredUri", "We are loading this new URL: '" + removeQueryParametersOrRedact(str) + "' with original requestHeaders appended.");
webView.loadUrl(str, this.mRequestHeaders);
}
private String removeQueryParametersOrRedact(String str) {
String str2 = TAG + ":removeQueryParametersOrRedact";
try {
return StringExtensions.removeQueryParameterFromUrl(str);
} catch (URISyntaxException e) {
Logger.errorPII(str2, "Redirect URI has invalid syntax, unable to parse", e);
return "redacted";
}
}
private void returnResult(RawAuthorizationResult.ResultCode resultCode) {
getCompletionCallback().onChallengeResponseReceived(RawAuthorizationResult.fromResultCode(resultCode));
}
private void returnError(String str, String str2) {
getCompletionCallback().onChallengeResponseReceived(RawAuthorizationResult.fromException(new ClientException(str, str2)));
}
@Override
public void onReceivedClientCertRequest(WebView webView, final ClientCertRequest clientCertRequest) {
String str = TAG + ":onReceivedClientCertRequest";
Principal[] principals = clientCertRequest.getPrincipals();
if (principals != null) {
for (Principal principal : principals) {
if (principal.getName().contains(DEVICE_CERT_ISSUER)) {
Logger.info(str, "Cancelling the TLS request, not responding to TLS challenge triggered by device authentication.");
clientCertRequest.cancel();
return;
}
}
}
AbstractCertBasedAuthChallengeHandler abstractCertBasedAuthChallengeHandler = this.mCertBasedAuthChallengeHandler;
if (abstractCertBasedAuthChallengeHandler != null) {
abstractCertBasedAuthChallengeHandler.cleanUp();
}
this.mCertBasedAuthFactory.createCertBasedAuthChallengeHandler(new CertBasedAuthFactory.CertBasedAuthChallengeHandlerCallback() {
@Override
public void onReceived(AbstractCertBasedAuthChallengeHandler abstractCertBasedAuthChallengeHandler2) {
AzureActiveDirectoryWebViewClient.this.mCertBasedAuthChallengeHandler = abstractCertBasedAuthChallengeHandler2;
if (AzureActiveDirectoryWebViewClient.this.mCertBasedAuthChallengeHandler != null) {
AzureActiveDirectoryWebViewClient.this.mCertBasedAuthChallengeHandler.processChallenge(clientCertRequest);
} else {
clientCertRequest.cancel();
}
}
});
}
public void onDestroy() {
AbstractCertBasedAuthChallengeHandler abstractCertBasedAuthChallengeHandler = this.mCertBasedAuthChallengeHandler;
if (abstractCertBasedAuthChallengeHandler != null) {
abstractCertBasedAuthChallengeHandler.cleanUp();
}
this.mCertBasedAuthFactory.onDestroy();
}
public void finalizeBeforeSendingResult(RawAuthorizationResult rawAuthorizationResult, ISendResultCallback iSendResultCallback) {
AbstractCertBasedAuthChallengeHandler abstractCertBasedAuthChallengeHandler = this.mCertBasedAuthChallengeHandler;
if (abstractCertBasedAuthChallengeHandler == null) {
iSendResultCallback.onResultReady();
return;
}
abstractCertBasedAuthChallengeHandler.emitTelemetryForCertBasedAuthResults(rawAuthorizationResult);
AbstractCertBasedAuthChallengeHandler abstractCertBasedAuthChallengeHandler2 = this.mCertBasedAuthChallengeHandler;
if (!(abstractCertBasedAuthChallengeHandler2 instanceof AbstractSmartcardCertBasedAuthChallengeHandler)) {
iSendResultCallback.onResultReady();
} else {
((AbstractSmartcardCertBasedAuthChallengeHandler) abstractCertBasedAuthChallengeHandler2).promptSmartcardRemovalForResult(iSendResultCallback);
}
}
}