IITC-CE / ingress-intel-total-conversion

intel.ingress.com total conversion user script with some new features. Should allow easier extension of the intel map.
https://iitc.app
ISC License
285 stars 110 forks source link

IITCm for Android: gapi.auth2.authorize limitation #362

Closed le-jeu closed 1 year ago

le-jeu commented 4 years ago

gapi.auth2.authorize looks ok to be used in IITC, using either the google ingress account or another google account. But, on android device, the webview seems to break the gapi auth process as long as we ask the user for a prompt (consent or select_account). Apparently, the google popup is forbidden to close itself nor to send data back to the original window.

image

I don't know if this is some absolute limitation of android + gapi or if a solution exists. (android code or javascript). I explored javascript side without finding answer.

Example of authentication script (ask for a token)

// @author         jaiperdu
// @name           Authentication test
// @category       Misc
// @version        0.1.0
// @description    Simple authentication test

// use own namespace for plugin
window.plugin.authTest = function() {};

window.plugin.authTest.dialogHTML = null;

// web app client id with auth screen allowing https://intel.ingress.com as origin
window.plugin.authTest.CLIENT_ID = 'CLIENTID.apps.googleusercontent.com';

window.plugin.authTest.SCOPES = 'openid profile email';
window.plugin.authTest.TYPE = 'id_token permission';

window.plugin.authTest.authorize = function() {
  const options = {
    prompt: 'select_account', // or 'consent' (use 'none' for implicit auth if possible)
    client_id: this.CLIENT_ID,
    scope: this.SCOPES,
    response_type: this.TYPE
  };

  window.gapi.auth2.authorize(options, response => {
    if (response.error) {
      const err = `error: ${response.error}: ${response.error_subtype}`;
      alert(err);
      console.log(err);
      return;
    }

    alert(response.access_token);
    console.log(response.id_token, response.access_token);
  });
};

window.plugin.authTest.setupDialog = function() {
  $('#toolbox').append('<a id="authTest-authorize" onclick="window.plugin.authTest.authorize();">AuthTest</a> ');
};

var setup = function() {
  if (typeof window.gapi !== "undefined") {
    window.gapi.load("auth2", () => {
      window.gapi.auth2.enableDebugLogs(true);
    });
  }
  else {
    const script = document.createElement("script");
    script.type = "text/javascript";
    script.async = true;
    script.defer = true;
    script.src = "https://apis.google.com/js/platform.js";
    script.onload = () => {
      window.gapi.load("auth2", () => {
        window.gapi.auth2.enableDebugLogs(true);
      });
    };
    (document.body || document.head || document.documentElement).appendChild(
      script
    );
  }
  window.plugin.authTest.setupDialog();
};

related #277 #334

johnd0e commented 4 years ago

Do you think this is IITC fault?

Or WebView limitation?

What are we supposed to do with this issue?

le-jeu commented 4 years ago

I found a workaround for android source. From https://stackoverflow.com/questions/23308601/android-open-pop-up-window-in-my-webview and https://stackoverflow.com/questions/23211722/window-close-not-working-in-android-webview (and some other I lost the track)

This is a PoC and aims simplicity (with the cost of safety). I almost have no idea what I am doing, but it works so far.

index 2f79167c..ab639de9 100644
--- a/mobile/app/src/main/java/org/exarhteam/iitc_mobile/IITC_WebChromeClient.java
+++ b/mobile/app/src/main/java/org/exarhteam/iitc_mobile/IITC_WebChromeClient.java
@@ -5,6 +5,7 @@ import android.content.ClipData;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Build;
+import android.os.Message;
 import android.webkit.ConsoleMessage;
 import android.webkit.GeolocationPermissions;
 import android.webkit.JsPromptResult;
@@ -210,4 +211,23 @@ public class IITC_WebChromeClient extends WebChromeClient {
         return new IITC_JsDialogHelper(IITC_JsDialogHelper.PROMPT, view, url, message, defaultValue, result)
                 .shouldInterrupt();
     }
+
+    @Override
+    public boolean onCreateWindow(WebView view, boolean isDialog,
+        boolean isUserGesture, Message resultMsg) {
+
+        IITC_WebView newWebView = new IITC_WebView(mIitc);
+        view.addView(newWebView);
+        WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
+        transport.setWebView(newWebView);
+        resultMsg.sendToTarget();
+
+        return true;
+    }
+
+    public void onCloseWindow(WebView w){
+        if (mIitc.getWebView() != w)
+            mIitc.getWebView().removeView(w);
+        Log.d("onCloseWindow");
+    }
 }
diff --git a/mobile/app/src/main/java/org/exarhteam/iitc_mobile/IITC_WebView.java b/mobile/app/src/main/java/org/exarhteam/iitc_mobile/IITC_WebView.java
index 8e6fa710..629550a9 100644
--- a/mobile/app/src/main/java/org/exarhteam/iitc_mobile/IITC_WebView.java
+++ b/mobile/app/src/main/java/org/exarhteam/iitc_mobile/IITC_WebView.java
@@ -51,6 +51,7 @@ public class IITC_WebView extends WebView {
         mIitc = (IITC_Mobile) c;
         mSettings = getSettings();
         mSettings.setJavaScriptEnabled(true);
+        mSettings.setSupportMultipleWindows(true);
         mSettings.setDomStorageEnabled(true);
         mSettings.setAllowFileAccess(true);
         mSettings.setGeolocationEnabled(true);
johnd0e commented 3 years ago

@le-jeu @McBen Is this issue is still relevant? Could you put proposed fixes into PR?

johnd0e commented 3 years ago

related #277 [...]

What kind of relation is there? Is proposed code able to fix #277?

le-jeu commented 3 years ago

I don't know, I didn't test against this It's a weak relation

IITC is blocking popup while google uses ones in some cases.

after a second reading, the "Advenced Protection" looks like it needs the webview to access some device key that out of scope of this issue