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

inAppBrowser custom application scheme handling on android #99

Closed
wants to merge 13 commits into
base: master
from

Conversation

Projects
None yet
@osvso
Copy link

osvso commented Mar 26, 2015

Currently the inAppBrowser doesn't handle custom application scheme making it impossible to redirect back to the nativeCode from the embedded webView. The system browser handles such redirects without a problem, but due to security reasons in some cases usage of embedded view is more advisable.

inAppBrowser will allow back-to-the-app-redirections using applicatio…
…n's custom scheme

scheme can be configured in config.xml using "CustomAppScheme" proererty
@jcesarmobile

This comment has been minimized.

Copy link
Member

jcesarmobile commented Mar 26, 2015

I can't understand what this changes try to achieve. Looking at the code it launchs an intent to open an external app if the url is defined on the config.xml. But that can be done right now using the _system option

@osvso

This comment has been minimized.

Copy link
Author

osvso commented Mar 27, 2015

Maybe I'm missing something. The problem which we faced with the current inAppBrowser plugin implementation is that it doesn't allow to perform the redirection back to the application using custom scheme. Although the android:scheme is registered the webView in inAppBrowser returns err_unknown_url_scheme when trying to navigate back. It works without any problems on iOS, and also using system browser.

@osvso

This comment has been minimized.

Copy link
Author

osvso commented Mar 27, 2015

Due to security issues we don't want to use system browser.

@purplecabbage

This comment has been minimized.

Copy link
Contributor

purplecabbage commented Mar 27, 2015

It should not redirect, it should send a message to it's parent ( the application webview )
The parent should then dismiss it's child (InAppBrowser).

The parent gets notifications every time the location of the InAppBrowser changes, and can respond based on what the location.href is. Think oauth, and send the InAppBrower to #token=ACCESS_TOKEN or some other signal that you define.

@osvso

This comment has been minimized.

Copy link
Author

osvso commented Mar 28, 2015

I agree that it is responsibility of the parent to dismiss the inAppBrowser (fixed that), but from the other hand it is also responsibility of the webView to handle the redirect. Listening and interpreting redirections from to top level is possible and would probably work, but I consider it as not safe as it moves handling sensitive redirection to javascript layer which can be easily tampered. Also redirection handling will have to be placed within some android specific statement as it works on iOS.

@osvso osvso force-pushed the Onegini:master branch from 0bd58ee to ebca6c7 Mar 31, 2015

@iampeter

This comment has been minimized.

Copy link

iampeter commented Dec 17, 2015

Could this change be introduced? Seems that on some Android devices the "_system" parameter doesn't help with the custom URL scheme.

@caphun

This comment has been minimized.

Copy link

caphun commented Jan 7, 2016

I'm hitting the same problem with a custom scheme that is not on a page I control so cannot add the "_system" target. This fix seems to solve the problem. Are there plans to integrate this soon? If not what is the alternative?

@NGumby

This comment has been minimized.

Copy link

NGumby commented Feb 16, 2016

I think a better approach to communicate between an external website and the app, is to raise an event in shouldOverrideLoadUrl like this :

public boolean shouldOverrideUrlLoading(WebView webView, String url) {
            LOG.d(LOG_TAG, "shouldOverrideUrlLoading:" + url);

            if (url.startsWith(WebView.SCHEME_TEL)) {
                ...
            }
            else if (url.startsWith("myscheme:")) {
                try {
                    JSONObject obj = new JSONObject();
                    obj.put("type", "customevent");
                    obj.put("url", url);
                    sendUpdate(obj, true);
                    return true;
                } catch (JSONException ex) {
                    LOG.e(LOG_TAG, "URI passed in has caused a JSON error.");
                }
            }
            return false;
        }

add this to InAppBrowser.js

    function InAppBrowser() {
        this.channels = {
            'loadstart': channel.create('loadstart'),
            'loadstop': channel.create('loadstop'),
            'loaderror': channel.create('loaderror'),
            'customevent': channel.create('customevent'),
            'exit': channel.create('exit')
        };
    }

in your app, you can then do
appBrowser.addEventListener("customevent", function(event){console.log("My custom event raised:" + event.url)});

from the external website, you can then have a link like

<a href="myscheme://mycustomaction?someparam=value">Custom Action in the app</a>

It works pretty well, and you can parse the url to do the custom actions!

And this can be done in iOS also.

@JPustkuchen

This comment has been minimized.

Copy link

JPustkuchen commented Apr 7, 2016

I can confirm that this is really an important feature request. For example we want to use skype:// and whatsapp:// links within the webview. The problem is, that loadstart acts async and so even a workaround in the event to prevent loading the protocol as page is not cleanly possible.

A possible and safe solution (from my point of view) could be a new "beforeloadstart" event which allows to return false (to stop loading) and take the url parameter for custom handling. The url should not be prefixed by http:// like currently in loadstart. So we can introduce our own custom logic in JS without hacking the plugin simply be pre-checking the called URL (and its scheme).

What do you think?

@osvso

This comment has been minimized.

Copy link
Author

osvso commented Apr 27, 2016

I've changed the implementation a bit. Currently defining additional property with custom application scheme is not required anymore.

@moneytree-doug

This comment has been minimized.

Copy link

moneytree-doug commented Aug 5, 2016

I think this is an important feature for OAuth, has anyone figured out a work around?

@ljcljc

This comment has been minimized.

Copy link

ljcljc commented Aug 22, 2016

I have met with the same problem, has anyone fix this issue yet?

@moneytree-doug

This comment has been minimized.

Copy link

moneytree-doug commented Aug 22, 2016

@ljcljc I used @osvso 's library and it worked.

@ljcljc

This comment has been minimized.

Copy link

ljcljc commented Aug 22, 2016

@moneytree-doug Thanks for your reply.

Could you explain in detail how it works?

This is the link of @osvso https://github.com/apache/cordova-plugin-inappbrowser/pull/99/commits/01968d06004645fb6289d35c1ba31eb048c8620d

And, do I need to specify 'CustomSchema' in config.xml? Or it works automatically without any further configuration?

Thanks

@ljcljc

This comment has been minimized.

Copy link

ljcljc commented Aug 22, 2016

@moneytree-doug I finally figure it out. It works great. No other configurations needed.
@osvso Thanks for your excellent work! Save my day!

@JPustkuchen

This comment has been minimized.

Copy link

JPustkuchen commented Aug 22, 2016

@ljcljc : Could you please paste your final solution as example for all of us? That would help a lot :) Thank you!

@ljcljc

This comment has been minimized.

Copy link

ljcljc commented Aug 22, 2016

@JPustkuchen
Sure. You can checkout my repository, which I forked from @osvso , using cordova to install it.
https://github.com/ljcljc/cordova-plugin-inappbrowser

This is his change to the original version.
01968d0

Then, you can launch custom scheme within inappbrowser, and that should work fine. No other configuration needed.
Let me know if you have any questions using it.

@moneytree-doug

This comment has been minimized.

Copy link

moneytree-doug commented Aug 23, 2016

@JPustkuchen For example, I forked off the library so to use it as a plugin for cordova then you would do this: cordova plugin add https://github.com/moneytree/cordova-plugin-inappbrowser.git

@benbotto

This comment has been minimized.

Copy link

benbotto commented Feb 27, 2017

Seconding @moneytree-doug's statement that this is important for OAuth, or any protocol that requires redirects back to the app.

@ljcljc's fork corrects the problem, and we're using that in our Android builds. That version doesn't work correctly in iOS 10.2, however, so now we have custom builds for Android and iOS.

Using InAppBrowser, Opening a URL with a custom scheme works fine in iOS. Please make it work in Android, too!

Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	src/android/InAppBrowser.java
@steinwelberg

This comment has been minimized.

Copy link

steinwelberg commented Mar 17, 2017

We merged the original master branch into our branch again to make it completely up-to-date. I see that there we introduced other changes which should maybe not be included into this pull request, If that is what is keeping it from being merged I'm happy to create a new pull request with just the changes required to make the in app browser trigger the intent to handle a custom app scheme.

@cordova-qa

This comment has been minimized.

Copy link

cordova-qa commented Mar 17, 2017

Cordova CI Build has one or more failures.

Commit - Link
Dashboard - Link

Builder Name Console Output Test Report Device Logs
Windows 10 Store Link Link Link
iOS 9.3 Link Link Link
iOS 10.0 Link Link Link
Android 4.4 Link Link Link
Android 5.1 Link Link Link
@benbotto

This comment has been minimized.

Copy link

benbotto commented Jun 8, 2017

Any plan on accepting this pull request? This issue is more than two years old now, and there's still an inconsistency between iOS and Android that needs to be worked around.

@purplecabbage

This comment has been minimized.

Copy link
Contributor

purplecabbage commented Jun 8, 2017



[self.view addSubview:bgToolbar];

This comment has been minimized.

@shazron

shazron Jun 8, 2017

Contributor

What's the purpose of this code?

This comment has been minimized.

@steinwelberg

steinwelberg Jun 9, 2017

I honestly don't know. That's why I mentioned that this merge request somehow contains more stuff and I'm happy to create a 'clean' merge request.

This comment has been minimized.

@varunkumarm

varunkumarm Sep 20, 2017

@steinwelberg Can you please create the new merge request to get the essential part in? Clearly it looks like the extra code is causing the delay. It really helps to have the changes in the official branch than to fork and use.

@shazron

This comment has been minimized.

Copy link
Contributor

shazron commented Jun 8, 2017

From what I have read, it seems this is an Android problem -- so I'm not sure why the code changes in iOS are needed?

@wilsolutions

This comment has been minimized.

Copy link

wilsolutions commented Jul 27, 2017

Hi, please, can we get this in?

@infil00p

This comment has been minimized.

Copy link
Member

infil00p commented Sep 21, 2017

The code changes in iOS are delaying this. That being said, I don't know if blindly adding Application URIs in an InAppBrowser is a good idea in this case.

BTW: Does this have a JIRA issue attached to it anywhere?

@benbotto

This comment has been minimized.

Copy link

benbotto commented Sep 21, 2017

It's really been a long time waiting for this, over two years now! My team has been manually patching this piece of code to support custom application URIs for over a year. I'm not familiar enough with the Cordova code or project management to know why the iOS code changes are in there, or if there is a related JIRA ticket. That said, it sure is inconvenient that custom URIs work differently between iOS and Android. It seems like either both should work with custom URI schemes, or neither should (my vote's of course for the former).

Anyway, if adding application URIs in an InAppBrowser is not a good idea, then maybe someone can chime in on how to correctly implement something that requires a redirect back to an app. For example, we use OpenID Connect as a single sign-on solution. As part of the OpenID Connect spec the user agent (the mobile app) sends the user to a web page to authenticate. Then, on successful authentication, the user is redirected back to the client with an access token and id token. That redirect back requires handling a custom URI scheme, and it does not work in Android.

There's a long list of folks affected by this, and it's a burden for your users to have to use custom forks to implement something as common and simple as OAuth2. That's especially true since the solution, at least ostensibly, seems trivial. I for one would really appreciate a fix!

@purplecabbage

This comment has been minimized.

Copy link
Contributor

purplecabbage commented Sep 27, 2017

I blogged about this, and was able to do OAuth2 on iOS and Android without a need for protocols, or applications schemes.
https://medium.com/@purplecabbage/oauth2-in-apache-cordova-3a3ba059b184

@infil00p

This comment has been minimized.

Copy link
Member

infil00p commented Sep 27, 2017

Years ago, we added the Intent whitelist to Android to prevent Android from launching third-party intents that aren't whitelisted.

https://www.cvedetails.com/cve/CVE-2014-3500/

Since the whole point of the InAppBrowser as it was originally intended to be used is to allow untrusted Web content to be run in a sandbox away from the Cordova API, therefore we have to treat the contents themselves as untrusted. The problem is that there's no way to communicate that for the user except for the address bar, which can be disabled. It's not clear to the user that they actually made it to the proper OAuth page. Of course, we don't allow for the InAppBrowser to use Self-Signed Certificates, which does help mitigate this, but we have PRs open for people who want InAppBrowser to do so.

So, if Cordova can't open random intents, neither should the InAppBrowser, and I would actually consider it a bug for iOS to be able to do so. The InAppBrowser as it is currently designed could be prone to phishing attacks if we start giving it more and more functionality. Now, if someone was to make this robust enough to check the intent whitelist to see if Cordova could actually launch this intent, I might consider adopting this, but currently there's no way I'd accept this PR as it is.

@timbru31

This comment has been minimized.

Copy link
Contributor

timbru31 commented Dec 12, 2017

While I totally agree with you @infil00p, I'd like to point out that Chrome on Android on the other hand is able to launch any intent. It blocks custom url schemes like mycoolapp://, but allows the intent syntax of it to launch the app: intent://myIntent/#Intent;scheme=mycoolapp;package=com.mypackage;end
Maybe this is the direction forward?

For more information refer to this Chrome article: https://developer.chrome.com/multidevice/android/intents

@xingducai xingducai referenced this pull request Mar 8, 2018

Closed

android 增加自定义协议跳转 #261

0 of 3 tasks complete
@infil00p

This comment has been minimized.

Copy link
Member

infil00p commented Mar 8, 2018

@timbru31 I provided a way forward, and not a single person created a JIRA issue tracking this bug. I need the JIRA issue for the release notes for when this lands, and I would prefer if the people writing the feature/fixing the bug wrote it and explained the issue in their words as opposed to "Look at GitHub #99"

Anyway, this doesn't merge cleanly, and #261 does, so I'm going to keep going on that PR and close this one. People who want this feature can comment on that code, or you can get this to merge clean and re-open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment