Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How some apps are able to perform google login successfully in android webview?

As described here google has stopped supporting google login in webview. But there are apps in play store (all-in-one apps) who are displaying multiple progressive apps in their apps using webview and we can login there using google login.

So my question is how we can make this possible.

I have searched for questions on SO with following query.

Android 403: Error: Disallowed Useragent

Found lot of accepted answers with some of them containing various UserAgentString

Tried all of them but none of them helped. As UserAgentString doesn't helps always.

If login is being performed by opening new window then it doesn't work. Even though we define same UserAgentString with webview in onCreateWindow callback of WebChromeClient.

I have also tried searching for alternative of webview like CrossView etc. but they are not maintained from last 3 years.
I can't use custom chrome tabs as I can't hide address bar of custom chrome tab.

So please suggest me if it's really possible in webview or is there any alternative to webview.

EDIT - What I have tried so far.

WebView Initialization in onCreate()

webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setSupportMultipleWindows(true);
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webView.getSettings().setUserAgentString("Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36");
webView.getSettings().setGeolocationEnabled(true);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setAllowContentAccess(true);
webView.getSettings().setDatabaseEnabled(true);
webView.getSettings().setLoadsImagesAutomatically(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
webView.setWebChromeClient(new MyWebChromeClient());
enableHTML5AppCache(webView);

webView.loadUrl("https://www.makemytrip.com/");

Supporting methods and classes

private void enableHTML5AppCache(WebView mWebView) {

    mWebView.getSettings().setDomStorageEnabled(true);

    // Set cache size to 8 mb by default. should be more than enough
    mWebView.getSettings().setAppCacheMaxSize(1024 * 1024 * 8);

    // This next one is crazy. It's the DEFAULT location for your app's cache
    // But it didn't work for me without this line
    mWebView.getSettings().setAppCachePath("/data/data/" + getActivity().getPackageName() + "/cache");
    mWebView.getSettings().setAllowFileAccess(true);
    mWebView.getSettings().setAppCacheEnabled(true);

    mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
}

private class MyWebChromeClient extends WebChromeClient {

    @Override
    public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, android.os.Message resultMsg) {
        WebView newWebView = new WebView(getActivity());

        newWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
        newWebView.getSettings().setUserAgentString("Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.125 Mobile Safari/537.36");
        newWebView.getSettings().setLoadWithOverviewMode(true);
        newWebView.getSettings().setAllowContentAccess(true);
        newWebView.getSettings().setDatabaseEnabled(true);
        newWebView.getSettings().setLoadsImagesAutomatically(true);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            newWebView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }
        enableHTML5AppCache(newWebView);
        newWebView.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onCloseWindow(WebView window) {
                webView.removeView(window);
            }
        });
        view.addView(newWebView);
        WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
        transport.setWebView(newWebView);
        resultMsg.sendToTarget();
        return true;
    }

    @Override
    public void onCloseWindow(WebView window) {
        webView.removeView(window);
    }
}

Now, when I am using above UserAgentString google login is working where it's getting performed within same webView. But in above site when you click on login->google then it request for new window(I have return code above for new window - see onCreateWindow() method above) then it shows error 403 - Disallowed UserAgent.

like image 443
Nikhil Avatar asked Aug 24 '17 13:08

Nikhil


2 Answers

webSettings.setUserAgentString(webSettings.getUserAgentString().replace("; wv",""));

then you can login .

like image 192
HongSec Park Avatar answered Sep 28 '22 01:09

HongSec Park


Your code looks correct.

Google OAuth blocks WebView based on the user agent string, using your own user agent string makes the login available again (actually you only need to remove the "wv" from the original string).

Unfortunately there is a bug in WebView that when the setSupportMultipleWindows option is enabled the first navigation in the newly created WebView uses the default user agent string. See the bug tracker for more details: https://bugs.chromium.org/p/chromium/issues/detail?id=614951

The bug is fixed in Chromium 67 (the current version is 66), so the next version of WebView is expected to work fine. I haven't tested this myself though.

So either disable multiple windows support or wait for the next version of WebView to reach the users (if you really need a workaround you might experiment with reloading the page after first navigation or something similar).

like image 42
Simon Avatar answered Sep 28 '22 01:09

Simon