Closed Bug 743367 Opened 10 years ago Closed 10 years ago

Marketplace receipt verifier must check cryptographic integrity of receipt certification

Categories

(addons.mozilla.org Graveyard :: API, defect, P1)

x86
macOS
defect

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: bwalker, Assigned: andy+bugzilla)

References

Details

We need to add a Marketplace API to request reissue of receipt signed with revoked key, as described here:

https://wiki.mozilla.org/Apps/WebApplicationReceipt/GenerationService
Assignee: nobody → rtilder
Blocks: 698116
Blocks: 735054
No longer blocks: 698116
see also 743362
Off the top of my head, I can imagine a mozApps API, like:

  navigator.mozApps.requestNewReceipt(app.receipts[0])

The client would parse the receipt, find some data about how to reissue it, and then go through that process (it probably doesn't need user intervention of any sort?) and end up with a new valid receipt.

The server-side flow is kind of wonky in this case.  It would be something like requesting the marketplace to verify a receipt, getting a response that indicates a reissue is needed, then responding to the browser (in some application-specific way) that it needs to reissue the specific receipt, and then that triggers this receipt reissue API, and once it is through it starts the receipt verification flow over from the beginning.

Maybe other people have different thoughts.
The current proposal (in appendix D of the wiki page) is that it is the UA's job to notice that a receipt is close to expiry, and to request a refresh.  The idea was not to make certificate refresh something that the app would request - e.g. to avoid all of the tricky logic you describe there.  While the app could notice that a receipt has expired, and flag that fact to the user, it would not be the app's job to trigger a refresh.  (and in the normal course of events it wouldn't happen)

I propose that the receipt has a "refresh" URL encoded in it, as a sibling of verify and detail, which the UA can perform a GET request on to get a new one.  The one wrinkle to that flow is that it could trigger an authentication.
(In reply to Michael Hanson from comment #3)

- that would apply to expired receipts, but would it apply to revoked receipts (or revoked keys on receipts)?  Is it okay to simply leave the receipts in the wild until their expiration time comes?
(In reply to Ian Bicking (:ianb) from comment #4)
> - that would apply to expired receipts, but would it apply to revoked
> receipts (or revoked keys on receipts)?  Is it okay to simply leave the
> receipts in the wild until their expiration time comes?

Current thinking is that, depending on the severity of the breach, it may be okay to leave them in the wild until they expire.  The signing keys can be constructed with relatively short validity periods while we get comfortable with the operational security of the system.

If there is a spectacular breach, we may need a way to signal all WebRTs to refresh their receipts.  This could be done with a hotfix.  Otherwise, apps that are affected by a breach could direct users to a page at the Marketplace for an explicit reissue.

Right now, I do not believe that we need a new API from the Marketplace to request a reisssue.  In the spec, we state that the Marketplace can call install() again with a fresh receipt, without prompting the user.  Is that still correct?
I am not sure what the behavior of reinstallation is right now, that needs to be confirmed.

Perhaps a way to handle a hard failure of a receipt could have the Marketplace verification respond with a URL that the browser/user-agent can browse to where the Marketplace can do whatever it might want to do to repair the receipts (including authentication, and reinstallation to refresh/add receipts).
Okay, given that this is the Marketplace verification side of the equation, I am going to rename this bug and reframe it.

The Marketplace Receipt Verifier (that is, the URL exposed in the "verify" field of a receipt) should:

1. Receive a POSTed certified receipt.
2. Verify the cryptographic integrity of the receipt.  This will probably include climbing a certificate chain, and, at the top of the chain, using a public key discovered from our issuer endpoint.  This can be cached for a pretty long time.
3. If the receipt fails cryptographic validation, fail noisily.  As suggested by ianb, we could provide a URL with more information, but I'm not sure we have that flow worked out yet.
4. If the receipt fails integrity validation (an expiration window doesn't line up, a price limit is exceed), fail very noisily with internal alerts, because this looks like an attack
5. If the receipt passes validation, check against the internal purchase database to make sure the underlying transaction has not been refunded/invalidated
6. Return happily to caller with business status

Reissuance of a receipt is fundamentally a user-agent-to-store interaction, and should be driven by a "refresh" property of a receipt, invoked at the UA's discretion.  As Ian notes, we could add a method to the app-to-client (mozApps) API for this, but the marketplace doesn't need a new API for that.
Summary: add Marketplace API to request reissue of receipt signed with revoked key → Marketplace receipt verifier must check cryptographic integrity of receipt certification
Duplicate of this bug: 743362
Assignee: rtilder → amckay
Priority: -- → P1
Target Milestone: --- → 6.5.1
Target Milestone: 6.5.1 → 6.5.2
Done, too many commits to post here.
Status: NEW → RESOLVED
Closed: 10 years ago
Resolution: --- → FIXED
Product: addons.mozilla.org → addons.mozilla.org Graveyard
You need to log in before you can comment on or make changes to this bug.