Closed Bug 1037662 Opened 10 years ago Closed 10 years ago

Grant Firefox Accounts (FxA) access to web payment providers

Categories

(Core :: DOM: Device Interfaces, defect, P1)

defect

Tracking

()

VERIFIED FIXED
mozilla34

People

(Reporter: kumar, Assigned: fabrice)

References

Details

(Whiteboard: [dependency: marketplace])

Attachments

(4 files, 1 obsolete file)

A web payment provider (https://wiki.mozilla.org/WebAPI/WebPaymentProvider) is a website that runs inside a chrome window that is controlled by navigator.mozPay().

The JavaScript running on a payment provider must be able to access FxA, probably with code like this:

navigator.mozId.watch(
  wantIssuer: 'firefox-accounts',
  ...
);

Payment provider websites do not have permissions the same way packaged apps do. Typically, we expose privileged APIs to payment providers as properties of window.mozPaymentProvider (https://wiki.mozilla.org/WebAPI/WebPaymentProvider#API) but that may or may not make sense here.
No longer blocks: 938993
No longer depends on: 961794
Blocks: 1007956
Sam, this was identified as a FxA/Marketplace 2.0 blocker.
Flags: needinfo?(spenrose)
Given that currently we restrict to certified and privileged apps, I would say that yes we are blocked here.
Flags: needinfo?(spenrose)
It would seem hard to confirm that FxA fully satisfied this use case without a full integration test (even if manual).  While there are identified and known problems around permission, I can imagine other problems with the nested containers and windows.

Is there a workaround for 2.0?  Staying with Persona?  Using OAuth?
Priority: -- → P1
We can use the OAuth flow until this is available. However, this will mean requiring login every time a payment is done, which obviously is a regression from the Persona behaviour.
Component: Payments/Refunds → DOM: Device Interfaces
Priority: P1 → --
Product: Marketplace → Core
Version: Avenir → unspecified
Blocks: 897156
Some people were confused about what this bug is asking for. Here's another summary:

- An app accesses FxA like this https://github.com/mozilla-b2g/gaia/blob/3a6bc02d3218185240847e433683ccef285188ad/apps/settings/js/findmydevice.js#L25
- The app needs to have this permission: https://github.com/mozilla-b2g/gaia/blob/3a6bc02d3218185240847e433683ccef285188ad/apps/settings/manifest.webapp#L36
- A payment provider is a webpage that runs inside a custom window (the Trusted UI)
- In the Trusted UI there is no concept of an app or its permissions. For example, any app can take in-app payments by working with the navigator.mozPay() API.
- How can a payment provider webpage within the Trusted UI access FxA? We need a platform change for this, maybe by explicitly granting a permission around here? http://dxr.mozilla.org/mozilla-central/source/b2g/chrome/content/payment.js#470
Kumar, thanks for the clarification and my apologies for being slow on the uptake that you expected to see a patch for this (I am "some people" :-)). It will be quite a challenge to get something like this landed for 2.0, even if it is The Right Thing To Do, which is not clear to me yet. The security review for 2.0 is based on the assumption that we have whitelisted apps which access FxA, and that they are at least privileged. Even enabling privileged apps required a late fire drill to fix a security issue, with a patch that was written quickly by the lead for one of the two privileged apps we envisioned supporting in 2.0, and the purpose of which is to force a password challenge when encountering a new RP (such as a new payment provider). We are also generally concerned about the stability of the Trusted UI, though perhaps issues there are orthogonal to how we solve this problem. Given the timeframe and the need for what feels like non-trivial security review, and the long-passed 2.0 string freeze, how should we best move forward? How do we weigh that against the Oauth repeated-challenge regression, noting that MP is starting with Oauth and that our team is going to explore (no promises!) switching to Oauth in the 2.2 time frame?
Whiteboard: [dependency: marketplace]
Sam: Why do apps need to specifically request permission to use FxA?

Regarding our next steps - it sounds like we should talk about the best way to fix this and make a patch that we land/test on trunk, and then have the conversation about uplifting to 2.0.

There is some skepticism whether oauth will work here, but even so it would mean logging in every time.

Do you want to talk on video?
(In reply to Wil Clouser [:clouserw] from comment #7)
> Sam: Why do apps need to specifically request permission to use FxA?

We needed to add the permission because without this permission, any web page could silently read the users email address. See https://bugzilla.mozilla.org/show_bug.cgi?id=1028398

Fernando proposed an alternative to the permission in this comment: https://bugzilla.mozilla.org/show_bug.cgi?id=1028398#c3

Perhaps this (or some combination or permissions for privileged apps, and prompting for web pages) might be a solution here? (especially if we can somehow restrict it to trusted UI?)
Otherwise, another option maybe to whitelist URLs list as payment provider URLs based on the whitelist contained in the preference (dom.payment.provider.*). I think this would be OK if we could somehow guarantee that the URL was opened in trusted UI (but I am not sure how to do that).
(In reply to Paul Theriault [:pauljt] from comment #8)
> (In reply to Wil Clouser [:clouserw] from comment #7)
> > Sam: Why do apps need to specifically request permission to use FxA?
> 
> We needed to add the permission because without this permission, any web
> page could silently read the users email address. See
> https://bugzilla.mozilla.org/show_bug.cgi?id=1028398
> 
> Fernando proposed an alternative to the permission in this comment:
> https://bugzilla.mozilla.org/show_bug.cgi?id=1028398#c3
> 
> Perhaps this (or some combination or permissions for privileged apps, and
> prompting for web pages) might be a solution here? (especially if we can
> somehow restrict it to trusted UI?)

The patch that was implemented throws up the password challenge the first time a given origin accesses FxA with privileged perms. I don't think there is a significantly different mozId()-based option for payments on the table, but if I am missing something please clarify.
(In reply to Paul Theriault [:pauljt] from comment #9)
> Otherwise, another option maybe to whitelist URLs list as payment provider
> URLs based on the whitelist contained in the preference
> (dom.payment.provider.*). I think this would be OK if we could somehow
> guarantee that the URL was opened in trusted UI (but I am not sure how to do
> that).

Do we know what attributes might hang off the trusted UI's window object indicating it as such? If we can get that far, we would know. I would suggest having a payments engineer start hacking ASAP, with me helping Gecko-side. It would be awesome if they could build from patches I sling at them. Meanwhile we need security to look at whatever we might be considering.
I'm assuming that what the payment provider does in the trusted UI is up to it?

Do payment providers other than mozilla/webpay rely on access to Persona/FxA for authentication?

Does mozilla/webpay trust marketplace? Would it be sufficient for marketplace to trigger authentication before it triggers the mozPay API and smuggle the user information in the signed mozpay JWT, perhaps in productData? Then webpay could rely on that (it's signed by marketplace presumably), rather than from the assertion?
(In reply to Sam Penrose from comment #11)
> Do we know what attributes might hang off the trusted UI's window object
> indicating it as such? 

Yes, web pages within the trusted UI (only) get window.mozPaymentProvider. http://dxr.mozilla.org/mozilla-central/search?q=mozPaymentProvider&case=true&redirect=true
(In reply to Chris Karlof [:ckarlof] from comment #12)
> Do payment providers other than mozilla/webpay rely on access to Persona/FxA
> for authentication?

No. Only Mozilla domains need FxA.

> 
> Does mozilla/webpay trust marketplace? Would it be sufficient for
> marketplace to trigger authentication before it triggers the mozPay API and
> smuggle the user information in the signed mozpay JWT, perhaps in
> productData? Then webpay could rely on that (it's signed by marketplace
> presumably), rather than from the assertion?

This wouldn't work because we also allow in-app payments from non-Marketplace apps. For example, Angry Birds could call navigator.mozPay() to open a payment flow in the Trusted UI without Marketplace having any direct involvement.
(In reply to Kumar McMillan [:kumar] (needinfo for quickness) from comment #5)
> - How can a payment provider webpage within the Trusted UI access FxA? We
> need a platform change for this, maybe by explicitly granting a permission
> around here?
> http://dxr.mozilla.org/mozilla-central/source/b2g/chrome/content/payment.
> js#470

Just to be clear here, can we check its not the payment provider webpage (eg Bango) that has to access FxA. Rather its the mozilla hosted pages at the URL defined in the prefs (for example http://dxr.mozilla.org/mozilla-central/source/webapprt/prefs.js#72) that has to access FxA. Once the Mozilla hosted pages have access to the FxA information, it passes limited identity information onto the payment provider (eg Bango).
Attached patch untested wip (obsolete) — Splinter Review
Untested, but the idea is to grant the firefox-accounts permission to payment providers when they are loaded in the trusted UI.

If someone could help conduct testing that would be great!
I have a build with this patch applied, but I don't know how to actually get payments flow loaded. Can someone explain how to test this? 

Oddly, the persona flow in the marketplace app seems to load in the marketplace app, not in the system app, which was a little unexpected (i thought this used trusted UI as well, but I guess not).
Flags: needinfo?(kumar.mcmillan)
Flags: needinfo?(kumar.mcmillan)
Oops. I meant to comment that I emailed Paul instructions on how to set up payments for local testing. If anyone else needs that, let me know.
So testing this using the information provided by Kumar:

- On custom build with the WIP patch:  I get to enter pin code part, this works, but the payment fails after entering PIN code (seems to timeout while trying to retrieve transaction)
- On  the regular build, I get a payment cancelled error without leaving the pay alt app.

So from what I can tell the payment flow is getting my id with Fabrice’s patch (note: it gets my persona id, NOT Firefox Accounts id though…I assume that is expected.) Hard to tell without working end to end though.
I attached logcat for the timeout on the patched device above.
Sorry, I just saw this bug.

(In reply to Paul Theriault [:pauljt] from comment #19)
> 
> So from what I can tell the payment flow is getting my id with Fabrice’s
> patch (note: it gets my persona id, NOT Firefox Accounts id though…I assume
> that is expected.) Hard to tell without working end to end though.

How did you triggered the FxA flow? Did you specify the "wantIssuer": "firefox-accounts" parameter in the mozId.watch() call? Check [1]


(In reply to Paul Theriault [:pauljt] from comment #17)
> I have a build with this patch applied, but I don't know how to actually get
> payments flow loaded. Can someone explain how to test this? 
>

I know Kumar already emailed some instructions, but I'll write them also here just in case anyone else wants to try.

I guess the easiest way to test this is by writing a mock payment provider that can be a simple static HTML that makes the appropriate mozId calls. Once you have it, you'll need to tell mozPay to use this payment provider for a specific JWT type. To do that, you need to add an entry to your preferences like in [2] with the details of your mock payment provider. After that, you will need to create a JWT with the "typ" parameter set to the one that you specified for your mock payment provider in the preferences and call navigator.mozPay with this JWT from a test app. That should open the trusted UI embedding your mock payment provider.

> Oddly, the persona flow in the marketplace app seems to load in the
> marketplace app, not in the system app, which was a little unexpected (i
> thought this used trusted UI as well, but I guess not).

I don't understand this. The Persona flow is supposed to use the trusted UI.

[1] https://developer.mozilla.org/en-US/docs/Firefox-Accounts-on-FirefoxOS
[2] https://wiki.mozilla.org/WebAPI/WebPayment#Testing
What is supposed to be the audience for the assertions requested by the payment provider via FxA? Are we specifying any audience or we just defer to the mozId implementation to set the origin of the payment provider as the audience?

Note that we only allow certified apps to specify an audience different than its origin [1].

[1] https://mxr.mozilla.org/mozilla-central/source/dom/identity/nsDOMIdentity.js#651
Flags: needinfo?(kumar.mcmillan)
Hey all, I put together a fake provider (as ferjm suggests) which will make it easier to test this patch. With this fake provider I can see ERROR_NOT_AUTHORIZED_FOR_FIREFOX_ACCOUNTS within Trusted UI which is what we want to solve so it can be used to test Fabrice's patch.

Instructions:

- Add these prefs to your device or Gaia build (put them in build/config/custom-prefs.js and rebuild the profile):

pref("dom.payment.provider.6.name", "fakepay");
pref("dom.payment.provider.6.description", "fakepay");
pref("dom.payment.provider.6.uri", "http://people.mozilla.org/~kmcmillan/fakepay/pay.html?req=");
pref("dom.payment.provider.6.type", "fakepay/payments/pay/v1");
pref("dom.payment.provider.6.requestMethod", "GET");

- Open this in a B2G browser: http://people.mozilla.org/~kmcmillan/fakepay/start.html (http://mzl.la/1rthClN)
- tap 'Start fake payment'
- Check the console

Fernando's point about the audience is a good one though. After we solve the permission error, how do we solve the audience error? What should the audience be set to?
Flags: needinfo?(kumar.mcmillan)
I think we figured out the audience question. We want to leave audience blank so that it will be derived from window.location in our case (which is our payment provider that gets the assertion).
I forgot to mention that you may need this pref to see mozId errors:

pref("toolkit.identity.debug", true);
Attached image Screenshot
Thanks Kumar and Fabrice!

I managed to test this patch and there are two main issues.

The first one is that we are requesting a silent assertion, which means that the fxa dialog won't be triggered even if we don't have a valid account. I didn't have time to debug it properly, but it should be easy to fix.

The other issue is that system dialogs are supposed to be shown on top the trusted UI, but they currently don't do that. See the attached screenshot.
(In reply to Fernando Jiménez Moreno [:ferjm] from comment #27)
> The first one is that we are requesting a silent assertion, which means that
> the fxa dialog won't be triggered even if we don't have a valid account. I
> didn't have time to debug it properly, but it should be easy to fix.
> 

This is just because the fake provider is only doing .watch(). Doing .request() should solve it.
This patch fixes the system dialog vs trusted UI issue for me.
Attachment #8461007 - Flags: feedback?(alive)
> I think we figured out the audience question. We want to leave audience blank so that it will be derived from window.location in our case (which is our payment provider that gets the assertion).

Yeah. :) Overriding the audience is only available to certified apps, and even then it's an anti-pattern. It should always get the audience from the origin of the requester.
Comment on attachment 8461007 [details] [review]
Link to Github pull-request: https://github.com/mozilla-b2g/gaia/pull/22084

Not reading the whole comments but the patch looks sane.
Attachment #8461007 - Flags: feedback?(alive) → feedback+
Comment on attachment 8461007 [details] [review]
Link to Github pull-request: https://github.com/mozilla-b2g/gaia/pull/22084

Thanks Alive! I should have actually asked for r? instead of feedback.
Attachment #8461007 - Flags: review?(alive)
Comment on attachment 8460014 [details] [diff] [review]
untested wip

Review of attachment 8460014 [details] [diff] [review]:
-----------------------------------------------------------------

::: dom/payment/Payment.jsm
@@ +58,5 @@
>      } catch(e) {
>        this._debug = false;
>      }
> +
> +    this._debug = true;

This needs to go away in the final patch :)

@@ +64,5 @@
> +    let self = this;
> +    Services.obs.addObserver(function(aSubject, aTopic, aData) {
> +      self.registeredProviders = {};
> +      self.registerPaymentProviders();
> +    }, "webapps-registry-ready", /* ownsWeak */ false);

Not a big deal, but we are already lazy loading the payment providers at https://mxr.mozilla.org/mozilla-central/source/dom/payment/Payment.jsm#76

In any case, if there is a good reason for moving the registration step here:
* we should remove the "webapps-registry-ready" observer
* you can use a fat arrow function and get rid of "self".

@@ +205,5 @@
>          nums.push(match[1]);
>        }
>      }
>  
> +    let appsService = Cc["@mozilla.org/AppsService;1"]

This block should probably be b2g only code.

@@ +235,5 @@
>            description: branch.getCharPref("description"),
>            requestMethod: branch.getCharPref("requestMethod")
>          };
> +
> +        // Let this payment provider access the firefox-accounts API when

Also B2G only
Attached patch gecko patch v2Splinter Review
Addressing comments. I don't remember any good reason for doing the registration in the webapps-ready observer, so I just removed that part. Doing a bit of testing with this patch would be good though.
Attachment #8460014 - Attachment is obsolete: true
Attachment #8462678 - Flags: review?(ferjmoreno)
Whiteboard: [dependency: marketplace] → [repoman]
Attachment #8461007 - Flags: review?(alive) → review+
Comment on attachment 8462678 [details] [diff] [review]
gecko patch v2

Thanks Fabrice!
Attachment #8462678 - Flags: review?(ferjmoreno) → review+
Whiteboard: [repoman] → [dependency: marketplace]
Priority: -- → P1
https://hg.mozilla.org/mozilla-central/rev/f8306fd76d3f
Status: NEW → RESOLVED
Closed: 10 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla34
Hey Fernando, I tried out your patch using desktop B2G with the latest m-c and gaia. I did not try flashing a device. Everything seems to work ok but when I log out of Firefox Accounts and retry the flow, the buttons on the bottom are cut off. Is this also happening on device or only on desktop B2G?

Example of starting an FxA flow from the Trusted UI:
http://cl.ly/image/3j3l1U3M0V0R
http://cl.ly/image/3l2V1U2w0c2G
Flags: needinfo?(ferjmoreno)
Kumar the button cut-off is not related to this patch; see:

  https://bugzilla.mozilla.org/show_bug.cgi?id=1038980

and various others.
Flags: needinfo?(ferjmoreno)
ok. The layout is slightly different in the Trusted UI so I commented on that bug to make sure our scenario is accounted for.

As for FxA within the Trusted UI, I can verify that it is working now. Thanks ferjm!
Status: RESOLVED → VERIFIED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: