Skip to content
This repository

Support environments without popups (phonegap, etc.) #2034

Open
callahad opened this Issue July 13, 2012 · 85 comments
Dan Callahan
Owner

Several folks on dev-identity are asking about getting BrowserID to work with things like PhoneGap. Apparently one of the primary issues is opening a popup: it opens in a browser outside of the PhoneGap application, breaking the connection between Persona and the app.

Dan Callahan
Owner

I imagine that simply redirecting into and out of our login flow, instead of using a popup, might Just Work with the Observer API, since we would automatically fire an assertion when landing back on the RP...

Ben Adida

@callahad yes, that's exactly the idea I've been discussing with Dan for Chrome/iOS support and UIWebView support.

Sean McArthur
Collaborator
Ben Adida

@seanmonstar I'm with you except.... what other option do we have? Eventually I'd like Firefox to act as the Persona implementation, no passwords. But that's a bit further down the line.

Sean McArthur
Collaborator
vthunder

That would be possible on iOS, apps use custom protocol handlers to do that. But having to download a second app is, IMO, a non-starter. Our only hope is to piggy-back onto another app (like Firefox or Marketplace).

Max Ogden

there is a plugin for phonegap called ChildBrowser that is cross-platform and lets you open browser window popups for doing things like oauth. it can be used right now for browserid on phonegap

Brock Whitten

Happy to see this issue on the list. This is an important use case to cover.

As @maxogden says, ChildBrowser is the way to go. The problem is that persona (as far as I know) doesn't give you control over how the popup window opens.

Dan Callahan
Owner

This feels really high priority, but low urgency at the moment. It'd be awesome to have a really well fleshed out mobile story in Q3. Especially with Chrome on iOS needing this, etc.

Shane Tomlinson
Collaborator

Making this the new consolidated tracker bug so we can close down others.

issue #75
issue #428
issue #1822
issue #1870
issue #1946

Brian Warner
Owner

This feels like a candidate for the new beta2-req label.

Lloyd Hilaiel

now part of our Q3 goals... :+1: to the beta2 label.

Bill Walker
Owner

I have similar symptoms, Ben asked me to mention them here.

Steps to reproduce:

  1. visit marketplace.mozilla.org from Mobile Safari on iPhone 4 running iOS 5.
  2. choose "Add to Home Screen" from links at the bottom
  3. launch the newly created marketplace icon in the home screen
  4. click on the "log in / register" button
  5. sit at the "Connecting to Persona..." screen forever
Daniel Gagnon

It should also be possible to use the redirection even if you aren't on a mobile app.

I have a use case where a forum I use supports single sign on by opening my "login page" in a popup. My login page would simply use the persona redirection to do its job. Right now, it gives me a popup opening a new popup.

Chris Anderson

Just want to add that I was able to reproduce @wfwalker's 5 steps on iPad running iOS 6.1

As someone trying to put together a PhoneGap app, it would definitely be helpful to have a comment on this bug with an idea of the priority or the blockers for adding robust PhoneGap support. I'm about to brute-force my app to work, which probably won't be pretty, and if there was a little more guidance about design issues, I'd be more likely to do work that could be contributed back to Browserid.

If my brute force hacks are at all illuminating, I'll follow up with links.

Mark Nutter

Decided not to use Persona as a result of this issue. Definitely high priority if you ask me.

Ben Adida

@marknutter thanks for the feedback, we are working on this and we do plan a fix. Please consider watching this bug and adding Persona once we've addressed your issue!

Mark Nutter

What's the general plan for solving this problem? An in-page javascript modal or something? Also, how can I contribute as a developer?

Ben Adida

@marknutter I'll let @seanmonstar give you details, but high-level we're thinking that we'll detect when popups are not possible and implement a redirection-based flow. If you're using the Persona Observer API, i.e. .watch(), you don't need to do anything: it will just work.

Mark Nutter

oh, wait, so there's actually a way to do this manually right now via the Observer API? From the blog post about the Observer api: "Whenever a user clicks the login button on your site, you request() a verified email from your user, which opens the Persona dialog." - is that Persona dialog a popup window?

Dan Callahan
Owner

@marknutter Alas, not quite yet. I believe the plan is to have the Observer API automatically detect when popups aren't enabled, and then switch to a redirect-based workflow. So if you implement the Observer API now, you'll eventually get a popup-free experience where needed.

For what it's worth... what specific aspects of the popup blocked you from using Persona? Was it the lack of support in Phonegap or similar?

Daniel Gagnon
Mark Nutter

@callahad I was trying to use it on a web page that had been added as a homescreen web app on my iOS devices, and yes, I do plan on using phonegap with the app as well which will have the same problem.

Austin King
Owner
ozten commented March 06, 2013

Also, how can I contribute as a developer?

@marknutter look through this bug list and find a simpler, smaller bug. We'd love to help you work through a pull request. Once you get to know the codebase a bit more, you could help test the Phonegap patch when it's ready, tweak it, and fix any polish bugs to make sure it's any easy integration for other Phonegap devs.

Mark Nutter

@ozten sounds great, I'll give it a shot

Sean McArthur
Collaborator

@benadida @marknutter that will definitely help web browsers who currently have problems, like Chrome for iOS and Windows Phone, but it doesn't help native apps.

Chris Anderson

I've created a PhoneGap / Cordova plugin that uses the browserid-ios code to present a modal web view. It works but isn't fully featured yet. You can install it with the plugman tool.

Hopefully folks find this helpful in the time we are waiting for a more robust solution.

Mark Nutter

@jchris that is awesome, thanks for that!

James Shore

+1

This issue is affecting at least two of my users. The worst part about it is that it doesn't provide any useful information for people to diagnose the issue. Is there an ETA for a fix?

Jared Hirsch
Owner
6a68 commented April 02, 2013

Bumping to Beta 3. @jamesshore I don't have an ETA, maybe @lloyd or @callahad have thoughts.

Sean McArthur
Collaborator

I'm taking this, will continue work on the nopopup experiment I did last quarter, and see how many environments we can fix along the way.

Sandeep Shetty

@seanmonstar

  • Confused about your earlier comment "but it doesn't help native apps". Wouldn't the nopopup (redirect instead of popup) approach fix this for phonegap based apps?
  • Instead of detecting when popups are not possible could it just be an option so implementors can choose to always redirect?
  • Is there an ETA for this and can I contribute in any way to make this happen sooner?
Lloyd Hilaiel
lloyd commented April 27, 2013
Lloyd Hilaiel
lloyd commented April 27, 2013

@seanmonstar fwiw, I'm eager to review when you've got a candidate. This issue is 10 months open with 17 participants. let's get it done!

Austin King
Owner
ozten commented April 27, 2013

User Agent (or platform) sniffing is gross, but I'd rather have the shim give the best UX on a platform by platform basis.

Reasons
1) On the same platform, the Persona flow should always be consistent for security and ease of use
2) preferRedirect doesn't do anything on browsers with native implementations, right?

Sandeep Shetty

@lloyd Re native apps: Thanks. that makes sense.
@ozten : Agree with both your reasons but how do you handle something like Phonegap that does allow popups but outside the scope of the app?

Dan Callahan
Owner

(+1 to both of ozten's points.)

Austin King
Owner
ozten commented April 28, 2013

@sandeepshetty if we could detect that we were on phonegap and do a redirect based flow, I'd be all for it. My feedback is mainly about an RP controlled flag to switch the type of flow.

Sandeep Shetty

It looks like the only reliable way to detect phonegap is to register a callback for the deviceready event and set a flag in that callback to switch to a redirect based flow.

Sean McArthur
Collaborator

I agree with not having a request() flag. It should only use this method if the standard popup and window.opener don't work. I don't see a way to feature detect that without trying to open a popup before, so it will likely need to be browser sniffed, and compared against a list of known bad agents.

As I work on this, I'm wondering if it's needed to have a redirect flow. Since the watch() API adds a communication_iframe, we can store all the parameters in localStorage, open the dialog, check if we put stuff in localStorage, and then continue like everything is normal. The UX is better than redirecting the page in most cases.

@sandeepshetty ETA should be this coming train. To help development, you could help me understand PhoneGap, as I've never touched it. How would people use Persona in PhoneGap, and what happens when the popup opens? Can PhoneGap work like a normal browser, or should it use the internal API instead?

Sandeep Shetty

@seanmonstar There are two types of phonegap apps. One where you compile it yourself and the other is compiled on build.phoengap.com. I can only speak for the latter because that is what I use.

it looks like popups now work on phonegap. Since 4 months for apps that you compile yourself and since 3 months on build.phonegap.com.

When the popup opens it displays an error message:
persona-error-in-phonegap

Source of the test app: https://github.com/otxt/otxtapp/blob/master/index.html
You can test the app on your device by installing it from here: https://build.phonegap.com/apps/385137/share

Sorry did not understand your last question.

Sean McArthur
Collaborator

@sandeepshetty ok, so it can open popups. It looks like the popups don't include window.opener, but that's ok. That's what I'm looking to fix. So then, I'll work on this that should fix popups with broken openers, without a redirect flow. Once I have it working, I'll create an instance that you can load into your app and you can tell me if it works for you.

Lloyd Hilaiel
lloyd commented April 29, 2013

@ozten so yes, preferRedirect does nothing on a native persona implementation. Is that a reason to not expose it?

On a call with our webmaker friends, they seemed incredibly interested in this feature as the default. Further, popup hatred is the +1 community reaction to persona.

While a consistent experience is important, I'm not completely convinced we will sacrifice consistency by letting websites submit a preference.

If this had a meaningful impact on adoption, would we still refuse?

BUT, the decision to expose is orthogonal. it's a couple lines of code. let's not let it block the feature, which will help let persona work in more places.

Dan Callahan
Owner

Is that a reason to not expose it?

Consistency of experience. Persona should probably look / feel the same on the same device. That's how you'll recognize and trust it. If sometimes Persona looks like a popup and sometimes it looks like a big redirect, on the same browser, you'll probably think you're being phished.

Can we throw the opt-in question over to @skinny97214?

Sean McArthur
Collaborator

@sandeepshetty would you be able to test something for me in PhoneGap? I've been trying with Chrome for iOS, and wondering if the same problem exists elsewhere. Can you make a simple test case that opens a popup with var w = window.open(somewhere), and record the value of w.closed (in the original window) before and after closing the popup?

Sean McArthur
Collaborator

@sandeepshetty that's what I'm finding on Chrome for iOS. That's a bummer. It seems I can't use popups at all. I'll have make this use an actual redirect flow.

Sandeep Shetty

I now understand that a big disadvantage of the redirect flow, at least on Phonegap, is the absence of the address bar making it a prime target for phishing.

@seanmonstar Phonegap lets you listen to an exit event which I've tested. Could this be used instead for Phonegap to retain the popup flow?

Sean McArthur
Collaborator

It seems the exit event is non standard. I'd rather a flow that works for all (reasonably all) environments.

Shane Tomlinson
Collaborator

I'm taking it. I have taken @seanmonstar's original work and UA sniffed (gross) for Chrome for iOS and Windows Phone. It's gross, but it works. A working base that can be iterated from is better than not working at all.

Sean McArthur seanmonstar closed this in c580f5e August 15, 2013
Brock Whitten

Great work fellas! This is fantastic.

Lloyd Hilaiel

omg! :joy: well done.

Chris Anderson

My turn to play dumb. I tried following the instructions here -- eg including include.js in my PhoneGap app (default generated app but with <access origin="*" /> added to config.xml. In my application JavaScript I have this straightforward code, and it seems to do it's job just fine:

            if (navigator && navigator.id && navigator.id.request && navigator.id.watch) {
                navigator.id.watch({
                    loggedInUser : null,
                    onlogin : function(assertion) {
                        console.log("got assertion", assertion)
                    },
                    onlogout : function() {
                        console.log("logged out")
                    }
                })
                navigator.id.request();
            } else {
                console.log("persona login not available")
            }

But all that happens is I get my location changed (not bounced to Safari) to https://login.persona.org/sign_in and it just hangs with the spinner and "Connecting to Persona..." forever. I'm on iOS Simulator 6.1 or iPad with iOS 6.1.3. (On iPad there's no spinner, just a sideways chevron and a "Mozilla Persona. Simplified sign-in..." blurb at the bottom.)

FWIW I'm able to login to login.persona.org on my iPad Safari. (Or Simulator Safari)

What is the expected behavior? Should I expect to be bumped over to Safari? Should it stay in app but not hang? Am I following the wrong set of instructions?

Thanks to anyone who can set me on a non-hack path to success!

Dan Callahan
Owner

From looking at the patch that got merged, we're special-casing for Chrome on iOS and Windows Phone. I think we still need to add a UA detection string for phonegap :(

Dan Callahan callahad reopened this August 18, 2013
Shane Tomlinson
Collaborator

@callahad - that is right, we intentionally did not whitelist PhoneGap apps 1) do not have a test app, 2) the UA string changes depending on which version of PhoneGap is being used.

My feeling is that instead of UA sniffing for PhoneGap strings, we should either attempt to feature detect or create a Cordova plugin that covers .get and .getVerifiedEmail as well.

Chris Anderson
Shane Tomlinson
Collaborator

This is awesome info @jchris! That'll make it much easier for us to try and whip something together.

Chris Anderson

More hints... it might be sane to require the InAppBrowser plugin and then open the sign-in URL with the _blank target as documented here: http://docs.phonegap.com/en/3.0.0/cordova_inappbrowser_inappbrowser.md.html#window.open

Chris Anderson

I did another test of the garden variety Persona code on PhoneGap (same code as above but with the InAppBrowser plugin installed, and it gets to a different failure.

ios simulator screen shot aug 20 2013 7 40 43 am

Tavis Rudd

Is this fix (specifically Chrome on iOS) in the production version or is there some way to target an include.js payload with the fix?

Dan Callahan
Owner

@tavisrudd This is not yet live yet; it should be live on September 12th. (We have a biweekly production push schedule, to allow for localization and QA work, so things typically go live 2-3 weeks after being merged)

vthunder

This is awesome! :+1:

Dan Callahan
Owner

@tavisrudd This should now work in production on Chrome / iOS. Can you please confirm?

Tavis Rudd

Yep, it works fine now. Thanks :)

James Shore

Could somebody clarify what went into production? I just had a user complain that they couldn't login when using iOS Chrome.

Shane Tomlinson
Collaborator

@jamesshore - if a site uses the navigator.id.watch API, users of Chrome for iOS will be able to sign in. Chrome for iOS has a technical limitation where a dialog window is unable to communicate with its parent window. To get around this, we do what is called the "redirect flow" where a user is redirected from your site to Persona to authenticate, then back to your site. This only works for the navigator.id.watch API because neither .get nor .getVerifiedEmail provide us with a way to pass an assertion back to the RP after redirecting back from Persona. If your site uses .get or .getVerifiedEmail, please update to .watch - more information can be found on MDN.

James Shore

@shane-tomlinson Ah, that explains it. Yes, I'm using the old API. I've been meaning to update it anyway. Thanks!

Aravind

I have a use case for a preferRedirect option on navigator.id.request():

My application (Scrollback) is an IRC widget embedded on third party sites, and I'd like to open a popup to sign users in; if I use Persona there would now be two popups.

As an analogy, imagine if Gmail or Yahoo decided that their OAuth sign in pages wouldn’t support a redirect flow - the Persona identity bridges would have to spawn additional popups, and the experience would be terrible.

We're currently working around this issue by opening our login screen in an iframe on the third-party sites; this still results in three layers showing up: The host site, the scrollback login iframe, and the persona popup. You can see this happen on mozillaindia.org (which uses Scrollback).

Lloyd Hilaiel

@aravindet so this is the 4th similar request I've heard in the last several weeks. I think delegating control over the experience to the website via such a flag might be the right thing to do. please open another issue specifically about this. there's also a thread in the mailing list where we discussed this, feel free to start a new thread or re-open that one.

stadja

Right now, it works very well on my windows phone 7 lumia 710 !
thanks guys....
What a wonderful improvement :)

Alex Britez

I just attempted to build PhoneGap application using their Command Line process

    > cordova build ios
    > cordova emulate

I change my original get() call to a watch() . The sample i used was grabbed from here https://npmjs.org/package/express-persona

Javascript (should I be using another file?)

         <script src="https://login.persona.org/include.js"></script>

Watch code

      navigator.id.watch({
        onlogin: function(assertion) {
            var xhr = new XMLHttpRequest();
            xhr.open("POST", "/auth/browserid", true);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.addEventListener("loadend", function(e) {
                var data = JSON.parse(this.responseText);
                if (data && data.status === "okay") {
                    console.log("You have been logged in as: " + data.email);
                }
            }, false);

            xhr.send(JSON.stringify({
                assertion: assertion
            }));
        },
        onlogout: function() {
            var xhr = new XMLHttpRequest();
            xhr.open("POST", "/persona/logout", true);
            xhr.addEventListener("loadend", function(e) {
                console.log("You have been logged out");
            });
            xhr.send();
        }
    });

OnClick call to signal Login request

  navigator.id.request();

Also took an unsuccessful chance at using

  navigator.id.request({preferRedirect: true}); 

Everything works fine on the desktop, and iOS safari. Issue with PhoneGap and iOS Safari that has been added to HomeScreen. Am I missing an opt-in flag or something? According to previous comments is sounded like this should work.

Sean McArthur
Collaborator

A proposed declarative HTML API could solve most the rest of the issues involved, as it proposes POSTing back to a URL. See discussion: https://groups.google.com/d/topic/mozilla.dev.identity/12PW2Z-YPps/discussion

Ka-Hing Cheung

I am using persona on my own "app", which is now just a website (so no phonegap). Everything works fine, except if I use chrome on android and use the "add to home screen" feature to pin the website to the android home screen. If I do that then I get an error like #2034 (comment)

Lefteris Paraskevas

Hi.
I tried to use Persona with a standard PhoneGap application. I keep getting the same error as the one descirbed above.
From my understanding reading through this thread it seems that there has been a fix that went through however it still does not seem to work for me. I would appreciate any indication/help of how to resolve this.
Thank you
screen shot 2014-02-05 at 19 23 24

Dan Callahan
Owner

Looks like we may need to force PhoneGap / Cordova into the redirect workflow, instead of using popups. That would require editing this set of regexes to add PhoneGap detection: https://github.com/mozilla/persona/blob/32af5485ec5368cd0634d6ebd74f9a53a37f313f/resources/static/include_js/_include.js#L133-138

Patches welcome :)

(Whitelisting isn't ideal, but it's the most expedient thing we have at the moment.)

Lefteris Paraskevas

Don't know if you can find it with via userAgent but windows.cordova object might do the trick. What do you think?

Dan Callahan
Owner

That sounds reasonable. I can have something up for testing tomorrow, or you could grab the repo and try it yourself :)

Lefteris Paraskevas

Trying to test this locally. Not sure if I am doing it correctly:
1. npm install and npm start -> results in a local version running in http://127.0.0.1:10002
(checking the console i get the following errors:
GET http://localhost:10002/i18n/en/client.js 404 (Not Found)
Resource interpreted as Script but transferred with MIME type text/html: "http://localhost:10002/common/js/templates.js".
2. in my local include.js i changed the ipServer to point to the above.
3. added an extra check for window.cordova in the needsPopupFix
4.in layout.ejs I updated the reference from https://login.persona.org/include.js to my local include.js file.
Now when I open my phonegap app and click login I get a different error:
screen shot 2014-02-06 at 12 41 41
Checking my simulator's console with Safari, I see that I also get the same errors as described in step 1.
I am sure I miss something but can't really test this properly. Wish I could help more...
@callahad Let me know if you manage to get something up for testing or point me to what i am doing wrong so i can test it locally properly. Thanks a lot :-)

Dan Callahan
Owner

Doh! You're doing everything right, but I forgot that Cordova / PhoneGap will have a file:// URI instead of an http:// or https:// URI, and we limit the available schemes here: https://github.com/mozilla/persona/blob/32af5485ec5368cd0634d6ebd74f9a53a37f313f/resources/static/common/js/lib/urlparse.js#L72-73

Basically, using file:// opens up a lot of security issues: we can't easily differentiate between your app and other local apps, which opens the door for re-using assertions (see issue #3323).

This is going to sound ridiculously convoluted, but can you place the Persona login button in an iframe that points to an actual website? (Wow, this is not easy. Sorry!)

Lefteris Paraskevas

Thanks a lot @callahad
Yes I was pretty sure it was a problem with file://. Will try the iframe solution.
Just to be sure that I do not miss something obvious. There is no other way at the moment (eg. phonegap plugins) to get Persona to work as expected in a Phonegap application?

Dan Callahan
Owner

@lefos987 I haven't actually worked with PhoneGap, but earlier in the thread the Child Browser plugin was suggested. Maybe that will work for you?

Lefteris Paraskevas

Tried the iframe solution. Basically put my login/logout buttons in an iframe served by a nginx webserver. When I click login now:
1. the persona server does indeed receive a GET request for /sign_in but does not successfully process it.
2. debugging I see that my sign_in view is not served since one of the response headers is x-frame-deny which i guess stops it from working (although i get 200 back )
3. tried to add the /sign_in path in the X_FRAME_ALLOWED constant in lib/static/views.js and although I do not get the x-frame-deny response header the view is not successfully loaded (although i still get 200 back).
Just thought I would share this. Happy to try something else or change my approach if there are any suggestions.

Dan Callahan
Owner

@lefos987 Oof. I'm sorry again about the pain here. Realistically, this might not be cleanly solvable in the near future, as we don't have a lot of development bandwidth on our side, so you might want to go with an alternative option if getting your project out the door is the most important. On the other hand, if you're enjoying hacking on this, I'd love to review a pull request to make this work, or review a blog post detailing necessary workarounds to get Persona running under PhoneGap.

Lefteris Paraskevas

@callahad sure thing! Will keep trying to see what the best way to achieve this is.
Thanks for the suggestions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.