Apps/WebApplicationReceipt: Difference between revisions

 
(16 intermediate revisions by 6 users not shown)
Line 7: Line 7:
A receipt encodes an affirmation by a payment processor that a particular user has completed a transaction to acquire a particular digital product.  It contains the following fields:
A receipt encodes an affirmation by a payment processor that a particular user has completed a transaction to acquire a particular digital product.  It contains the following fields:


* <tt>typ</tt>: MUST be the string <tt>"purchase-receipt"</tt>
* <tt>typ</tt>: MUST be one of <tt>"purchase-receipt"</tt>, <tt>"developer-receipt"</tt>, <tt>"reviewer-receipt"</tt>, <tt>"test-receipt"</tt>.
* <tt>product</tt>: A URL identifying the product the receipt covers
* <tt>product</tt>: A JSON object identifying the product the receipt covers and any store specific data.
* <tt>user</tt>: An independently-verifiable identifier for the user that made the purchase.
* <tt>user</tt>: A JSON object containing an identifier that the issuing store can use to identify the user associated with this receipt.
* <tt>iss</tt>: A full domain (scheme, host, and port) for the store that issued the receipt
* <tt>iss</tt>: A full domain (scheme, host, and port) for the store that issued the receipt
* <tt>nbf</tt>: A "not-before" timestamp (seconds from 1970-01-01T00:00:00Z in UTC, RFC3339), indicating when the purchase was completed
* <tt>nbf</tt>: A "not-before" timestamp (seconds from 1970-01-01T00:00:00Z in UTC, RFC3339), indicating when the purchase was completed
* <tt>iat</tt>: An "issued-at" timestamp (seconds from 1970-01-01T00:00:00Z in UTC, RFC3339), indicating when this receipt was issued
* <tt>iat</tt>: An "issued-at" timestamp (seconds from 1970-01-01T00:00:00Z in UTC, RFC3339), indicating when this receipt was issued
* <tt>exp</tt>: (optional) An "expiry" timestamp (seconds from 1970-01-01T00:00:00Z in UTC, RFC3339), indicating when this receipt will expire
* <tt>detail</tt>: (optional) A URL that contains additional human- or machine-readable detail about the purchase
* <tt>detail</tt>: (optional) A URL that contains additional human- or machine-readable detail about the purchase
* <tt>verify</tt>: (optional) A URL that can be used by an authenticated application to verify a receipt
* <tt>verify</tt>: (optional) A URL that can be used by an authenticated application to verify a receipt
* <tt>reissue</tt>: (optional) A URL that can be used to re-issue a new receipt
=== the typ field ===
The <tt>typ</tt> identifies the type of the receipt. Not all types of receipts need to be accepted.
* <tt>purchase-receipt</tt>: A receipt issued when a transaction is completed. This type of receipt should be accepted by the app at all times.
* <tt>developer-receipt</tt>: A receipt issued to the developer of the app. Usually they will be issued by the store for the use of the developer. This receipt may have a short expiry.
* <tt>reviewer-receipt</tt>: A receipt issued to the reviewer of the app. Usually they will be issued by the store for reviewers of the app. This receipt only needs to be accepted during the review period. This receipt may have a short expiry.
* <tt>test-receipt</tt>: A receipt issued to test the app during development. This receipt SHOULD NOT be accepted, except during development. This receipt may have a short expiry.


=== the product field ===
=== the product field ===


The <tt>product</tt> field identifies the digital good whose sale is represented by the receipt.  Conventionally, it is a URL.  A URL representing the root of a domain, without a trailing slash (e.g. <tt>"https://someapp.com"</tt>), is conventionally defined to represent "a web application"; URLs rooted further inside the site are conventionally defined to represent "in-application purchases", and can use whatever path scheme is convenient to the developer and issuer of the receipt.
The <tt>product</tt> field identifies the digital good whose sale is represented by the receipt.  It is a JSON object structure, containing the following fields:
 
* <tt>url</tt>: A URL representing the root of a domain, without a trailing slash (e.g. <tt>"https://someapp.com"</tt>), is conventionally defined to represent "a web application"; URLs rooted further inside the site are conventionally defined to represent "in-application purchases", and can use whatever path scheme is convenient to the developer and issuer of the receipt.  Currently the following URLs schemes are supported: http://, https://, and app://(for packaged apps)
* <tt>storedata</tt>: A string that uniquely identifies this app or product for the verifier of the receipt.


=== the user field ===
=== the user field ===


The <tt>user</tt> field provides an identification of a human user that can be independently verified by the both the issuer and verifier of the receipt. It is a JSON object structure, containing the following fields:
The <tt>user</tt> field provides an identifier that the issuing store can use to identify the human user associated with this receipt. There is no requirement that any other actor be able to validate this field, or use its contents. It is a JSON object structure, containing the following fields:


* <tt>type</tt>: A string
* <tt>type</tt>: A string
* <tt>value</tt>: A string
* <tt>value</tt>: A string


The only supported value of <tt>type</tt> at this writing is <tt>email</tt>; the value, in this case, is a verified email address.
The default supported value of <tt>type</tt> is <tt>directed-identifier</tt>, and <tt>value</tt> is a unique user ID. To protect user privacy, the <tt>user</tt> field should not be an email address, or another identifier that the user or anyone else might recognize. Instead, the suggested implementation is to randomly generate a GUID for each transaction. The store should retain the GUID, and use it to link receipts to accounts, but it should be an unusable opaque identifier to all others.


=== the iss field ===
=== the iss field ===
Line 35: Line 49:
=== the nbf field ===
=== the nbf field ===


The <tt>nbf</tt> (not before) field identifies the time before which the receipt MUST NOT be accepted for processing. The processing of the nbf field requires that the current date/time MUST be after or equal to the not-before date/time listed in the nbf field. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew.
The <tt>nbf</tt> (not before) field identifies the time before which the receipt MUST NOT be accepted for processing. The processing of the nbf field requires that the current date/time must be after or equal to the not-before date/time listed in the nbf field. Implementers may provide for some small leeway, usually no more than a few minutes, to account for clock skew.


=== the iat field ===
=== the iat field ===


The <tt>iat</tt> (issued at) field identifies the time at which the receipt was issued. This claim can be used to determine the age of the token.
The <tt>iat</tt> (issued at) field identifies the time at which the receipt was issued. This claim can be used to determine the age of the token.
=== the exp field ===
The <tt>exp</tt> (expiry) field identifies the time at which the receipt will expire.


=== the detail field ===
=== the detail field ===


The <tt>detail</tt> field is a URL.  It is expected to resolve to a human-readable web page which contains detailed information about the receipt.  If a transaction log or refund capability is provided for the purchase, it is expected that this page will contain those functions.  The page may optionally contain machine-readable information about the transaction.  (TODO: Identify microdata fields?)
The <tt>detail</tt> field is a URL.  It is expected to resolve to a human-readable web page which contains detailed information about the receipt.  If a transaction log or refund capability is provided for the purchase, it is expected that this page will contain those functions.  The page may optionally contain machine-readable information about the transaction.  (TODO: Identify [[microformats]]/microdata fields?)


=== the verify field ===
=== the verify field ===


The <tt>verify</tt> field is a URL.  Is is used for automated verification of a receipt by application receivers.  See "Interaction with the verify URL", below.
The <tt>verify</tt> field is a URL.  This can be used for automated verification of a receipt by application receivers and is encourage.  See "Interaction with the verify URL", below.
 
=== the reissue field ===
 
The <tt>reissue</tt> field is a URL.  It is used for automated reissuing of receipts.


=== An example receipt ===
=== An example receipt ===
Line 53: Line 75:
  {
  {
   typ: "purchase-receipt",
   typ: "purchase-receipt",
   product: "https://grumpybadgers.com",
   product: {
    url: "https://grumpybadgers.com",
    storedata: "5169314356"
  },
   user: {
   user: {
     type: "email",
     type: "directed-identifier",
     value: "pseud-123gBm51jc56s@idprovider.com"
     value: "4fb35151-2b9b-4ba2-8283-c49d381640bd"
   },
   },
   iss: "https://appstore.com",
   iss: "https://appstore.com",
   nbf: 131360185,
   nbf: 131360185,
   iat: 131360188,
   iat: 131360188,
  exp: 141360188,
   detail: "https://appstore.com/receipt/5169314356",
   detail: "https://appstore.com/receipt/5169314356",
   verify: "https://appstore.com/verify/5169314356"
   verify: "https://appstore.com/verify/5169314356",
  reissue: "https://appstore.com/reissue/5169314356"
  }
  }


Line 78: Line 105:


# Verifying the cryptographic integrity of the receipt itself
# Verifying the cryptographic integrity of the receipt itself
# Authenticating the identity of the user presenting the receipt
# Checking the validity of the receipt with the issuer
# (optionally) Checking the validity of the receipt with the issuer


Verifying the receipt is according to the usual rules of JWT verification.  Public key discovery for the issuer is out of scope for JWT, but it is expected that verifying parties will receive public keys from their chosen payment providers through well-documented means, and that the <tt>iss</tt> field will be used to pick a public key from a previously-retrieved list.
Verifying the receipt is according to the usual rules of JWT verification.  Public key discovery for the issuer is out of scope for JWT, but it is expected that verifying parties will receive public keys from their chosen payment providers through well-documented means, and that the <tt>iss</tt> field will be used to pick a public key from a previously-retrieved list.


Authentication of the user is dependent on the user identification contained in the <tt>user</tt> field.  At this writing, the only supported user identification technique is a verified email address delivered through BrowserID.  BrowserID-savvy application runtimes will use the [[BrowserID Directed Identity Assertion]] API to allow verifying parties to retrieve a user assertion without requiring a consent popup during application launch.
If a payment provider offers a <tt>verify</tt> URL in the receipt, the verifying party is allowed to query that URL to determine the real-time status of the receipt.


If a payment provider offers a <tt>verify</tt> URL in the receipt, the verifying party is allowed to query that URL to determine the real-time status of the receipt.
=== Mozilla Marketplace Privacy Policy ===
 
The Mozilla Marketplace will have a privacy policy about what is logged when a receipt is verified.  


=== Interaction with the <tt>verify</tt> URL ===
=== Interaction with the <tt>verify</tt> URL ===


If the <tt>verify</tt> URL is present, the receiving party may verify it by issuing a GET request to it. The return value of this request is a JSON object with fields:
If the <tt>verify</tt> URL is present, the receiving party may verify it by issuing a POST request to it, where the message body contains the complete receipt.  
 
Currently checking the receipt validity with the issuer is the only way to confirm the status of the payment with the issuer. In future version of the receipt we hope to address this to provide more privacy for users by reducing the number of server checks.
 
The return value of this request is a JSON object with fields:
 
* <tt>status</tt>: A string, containing one of the values "ok", "pending", "refunded", "expired" or "invalid".
* <tt>reason</tt>: An optional field, normally only populated when a receipt is invalid, this will give you a reason it failed.
 
Application-level authentication on the verifyURL request is not strictly required, as the possession of a receipt proves that the application is already part of a trusted message flow.
 
Applications are free to re-query the verifyURL field as often as they see fit; whether this is a one-time or an every-time interaction, or something in between, is up to the application implementor to decide.
 
The verify URL will always return 200 for a successful check. Other possible response codes are 500 (server error) or a 503 (server busy). In the case of a 503, the client should retry at a later date. Clients should not assume that a 503 is a sign that the receipt is invalid.
 
== Firefox Marketplace receipts ==
 
Receipts issued by the Firefox Marketplace receipts differ from the spec in that they contain two parts. The receipt is split on a tilde (~). The second half is the receipt as discussed in this document. The first half of the receipt is a JSON Web Key:
 
  {u'exp': 1384565449,
  u'iat': 1353029449,
  u'iss': u'https://marketplace-dev-cdn.allizom.org/public_keys/test_root_pub.jwk',
  u'jwk': [{u'alg': u'RSA',
            u'exp': u'AQAB',
            u'kid': u'signer.dev.addons.phx1.mozilla.com',
            u'mod': u'AO4UtZW...'}],
  u'nbf': 1353029449,
  u'price_limit': 100,
  u'typ': u'certified-key'}


* <tt>status</tt>: A string, containing one of the values "ok", "pending", "refunded", or "invalid".
The fields are:


This verification is not required, but is provided to support real-time queries.  Receipt issuers SHOULD require application authentication on this call, to prevent enumeration attack.  Receipt issuers are encouraged to use a sparse, non-guessible receipt sequence ID if they do not authenticate verification calls.  (TODO: If it's just a status field, does enumeration really matter?  Perhaps none of this language is required.)
* <tt>jwk</tt>: The JSON Web Key token
* <tt>iss</tt>: A full domain (scheme, host, and port) for the store that issued this JSON Web Key
* <tt>nbf</tt>: A "not-before" timestamp (seconds from 1970-01-01T00:00:00Z in UTC, RFC3339), indicating when the transaction was completed
* <tt>iat</tt>: An "issued-at" timestamp (seconds from 1970-01-01T00:00:00Z in UTC, RFC3339), indicating when this transaction was issued
* <tt>exp</tt>: (optional) An "expiry" timestamp (seconds from 1970-01-01T00:00:00Z in UTC, RFC3339), indicating when this transaction will expire
* <tt>price_limit</tt>: always 100
* <tt>typ</tt>: always "certified-key"


== References ==
== References ==


* [http://self-issued.info/docs/draft-jones-json-web-token.html JSON Web Token]
* [http://self-issued.info/docs/draft-jones-json-web-token.html JSON Web Token]
* [http://tools.ietf.org/html/draft-ietf-jose-json-web-key-14 JSON Web Key]
* RFC 3339: Date and Time on the Internet: Timestamps
* RFC 3339: Date and Time on the Internet: Timestamps
Confirmed users
324

edits