Skip to content

Commit

Permalink
Merge pull request #2447 from brandonpage/enhanced-domain
Browse files Browse the repository at this point in the history
Optionally support use custom domain button in webview.
  • Loading branch information
brandonpage authored Aug 25, 2023
2 parents 09fdd34 + 8be650d commit 702159b
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import android.webkit.CookieManager;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
Expand Down Expand Up @@ -100,6 +101,7 @@
import java.util.SortedSet;
import java.util.UUID;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.regex.Pattern;

/**
* This class serves as an interface to the various
Expand Down Expand Up @@ -181,6 +183,9 @@ public class SalesforceSDKManager implements LifecycleObserver {
private boolean useWebServerAuthentication = true; // web server flow ON by default - but app can opt out by calling setUseWebServerAuthentication(false)

private boolean useHybridAuthentication = true; // hybrid authentication flows ON by default - but app can opt out by calling setUseHybridAuthentication(false)

private Pattern customDomainInferencePattern;

private Theme theme = Theme.SYSTEM_DEFAULT;
private String appName;

Expand Down Expand Up @@ -672,6 +677,28 @@ public synchronized void setUseHybridAuthentication(boolean useHybridAuthenticat
this.useHybridAuthentication = useHybridAuthentication;
}

/**
* Returns the pattern used to detect the use of "Use Custom Domain" input from login web view.
*
* @return pattern if set or null
*/
public synchronized Pattern getCustomDomainInferencePattern() {
return customDomainInferencePattern;
}

/**
* Detect use of "Use Custom Domain" input from login web view using the given regex.
* Example for a specific org:
* "^https:\\/\\/mobilesdk\\.my\\.salesforce\\.com\\/\\?startURL=%2Fsetup%2Fsecur%2FRemoteAccessAuthorizationPage\\.apexp"
* For any my domain:
* "^https:\\/\\/[a-zA-Z0-9]+\\.my\\.salesforce\\.com/\\?startURL=%2Fsetup%2Fsecur%2FRemoteAccessAuthorizationPage\\.apexp"
*
* @param pattern regex to use when detecting use of custom domain on login
*/
public synchronized void setCustomDomainInferencePattern(@Nullable Pattern pattern) {
this.customDomainInferencePattern = pattern;
}

/**
* Returns whether the IDP login flow is enabled.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
import com.salesforce.androidsdk.security.BiometricAuthenticationManager;
import com.salesforce.androidsdk.security.SalesforceKeyGenerator;
import com.salesforce.androidsdk.security.ScreenLockManager;
import com.salesforce.androidsdk.util.AuthConfigTask;
import com.salesforce.androidsdk.util.EventsObservable;
import com.salesforce.androidsdk.util.EventsObservable.EventType;
import com.salesforce.androidsdk.util.MapUtil;
Expand All @@ -99,6 +100,7 @@
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Pattern;

import okhttp3.Request;
import okhttp3.Response;
Expand Down Expand Up @@ -473,7 +475,7 @@ protected String getLoginUrl() {
* WebViewClient which intercepts the redirect to the oauth callback url.
* That redirect marks the end of the user facing portion of the authentication flow.
*/
protected class AuthWebViewClient extends WebViewClient {
protected class AuthWebViewClient extends WebViewClient implements AuthConfigTask.AuthConfigCallbackInterface {

@Override
public void onPageFinished(WebView view, String url) {
Expand All @@ -500,6 +502,7 @@ public void onPageFinished(WebView view, String url) {
}
}
}

EventsObservable.get().notifyEvent(EventType.AuthWebViewPageFinished, url);
super.onPageFinished(view, url);
}
Expand All @@ -522,8 +525,37 @@ public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request
return true;
}

boolean isDone = uri.toString().replace("///", "/").toLowerCase(Locale.US).startsWith(loginOptions.getOauthCallbackUrl().replace("///", "/").toLowerCase(Locale.US));
if (isDone) {
// Check if user entered a custom domain
String host = uri.getHost();
Pattern customDomainPattern = SalesforceSDKManager.getInstance().getCustomDomainInferencePattern();
if (host != null && !getLoginUrl().contains(host) && customDomainPattern != null
&& customDomainPattern.matcher(uri.toString()).find()) {
try {
String baseUrl = "https://" + uri.getHost();
LoginServerManager serverManager = SalesforceSDKManager.getInstance().getLoginServerManager();
LoginServerManager.LoginServer loginServer = serverManager.getLoginServerFromURL(baseUrl);

// Check if url is already in server list
if (loginServer == null) {
// Add also sets as selected
serverManager.addCustomLoginServer("Custom Domain", baseUrl);
} else {
serverManager.setSelectedLoginServer(loginServer);
}

// Set title to new login url
loginOptions.setLoginUrl(baseUrl);
// Checks the config for the selected login server
(new AuthConfigTask(this)).execute();
} catch (Exception e) {
SalesforceSDKLogger.e(TAG, "Unable to retrieve auth config.");
}
}

String formattedUrl = uri.toString().replace("///", "/").toLowerCase(Locale.US);
String callbackUrl = loginOptions.getOauthCallbackUrl().replace("///", "/").toLowerCase(Locale.US);
boolean authFlowFinished = formattedUrl.startsWith(callbackUrl);
if (authFlowFinished) {
Map<String, String> params = UriFragmentParser.parse(uri);
String error = params.get("error");
// Did we fail?
Expand All @@ -542,7 +574,8 @@ public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request
}
}
}
return isDone;

return authFlowFinished;
}

@Override
Expand Down Expand Up @@ -570,6 +603,15 @@ public void onReceivedClientCertRequest(WebView view, ClientCertRequest request)
SalesforceSDKLogger.d(TAG, "Received client certificate request from server");
request.proceed(key, certChain);
}

@Override
public void onAuthConfigFetched() {
SalesforceSDKManager manager = SalesforceSDKManager.getInstance();
if (manager.isBrowserLoginEnabled()) {
// This load will trigger advanced auth and do all necessary setup.
doLoadPage();
}
}
}

/**
Expand Down

0 comments on commit 702159b

Please sign in to comment.