diff --git a/articles/ui/ui.tex b/articles/ui/ui.tex index d1f95523b..c48d76494 100644 --- a/articles/ui/ui.tex +++ b/articles/ui/ui.tex @@ -825,9 +825,12 @@ X-Taler-Contract-Url: https://shop/generate-contract/42 \label{listing:http-contract} \end{figure*} +\subsubsection{Offer} + The offer URL of the Web shop can then initiate payments by sending a -\emph{contract proposal} (Figure~\ref{listing:json-contract}) to the wallet, either via the HTTP status -code {\tt 402 Payment Required} (Figure~\ref{listing:http-contract}), or via Taler's JavaScript API +\emph{contract proposal} (Figure~\ref{listing:json-contract}) to the +wallet, either via the HTTP status code {\tt 402 Payment Required} +(Figure~\ref{listing:http-contract}), or via Taler's JavaScript API (Figure~\ref{listing:contract}). The wallet then presents the contract to the user. The format of the contract is in an extensible JSON-based format defined by Taler and not HTML, as the rendering of @@ -836,16 +839,6 @@ representation of the terms and prices. In case that transaction fees need to be covered by the customer, these are shown together with the rest of the proposed contract. -If the customer approves the contract by clicking the ``Confirm -Payment'' button (Figure~\ref{subfig:payment}), their wallet signs the -contract with enough coins to cover the contract's cost, stores all of -the information in its local database, and transmits the payment to -the {\em payment} URI of the Web shop. Once the Web shop confirms the -payment, the wallet redirects the browser to the {\em fulfillment} URL -provided by the merchant (Figure~\ref{subfig:fulfillment}). - -\subsection{Browser security} - The Taler wallet operates from a securely isolated {\em background} context on the client side. The user interface that displays the contract and allows the user to confirm the payment is displayed by @@ -857,44 +850,62 @@ wallet's payment page (Figure~\ref{subfig:payment}), as such a page would still not have access to the private keys of the coins that are exclusive to the background context. -%The current Taler specification is written to accommodate for -%the rather restrictive set of APIs that WebExtension, a -%cross-browser extension API, provides. +If the customer approves the contract by clicking the ``Confirm +Payment'' button (Figure~\ref{subfig:payment}), their wallet signs the +contract with enough coins to cover the contract's cost, stores all of +the information in its local database, and redirects the browser to +the {\em fulfillment} URL provided by the merchant in the contract +(Figure~\ref{subfig:fulfillment}). -\subsection{Managing browser session state} +\subsubsection{Fulfillment} -% FIXME: this is where we probably want to revise quite a bit, -% including improving the description AND addressing the JS-less -% implementation. +The fulfillment URL uniquely identifies a purchase by some customer, +while the offer URL identifies a generic offer that is not specific to +a customer. The purchase identified by a fulfillment URL may have +been completed or still be in progress. The information contained in +the fulfillment URL must allow the merchant to restore the full +contract (including a unique transaction identifier) that was +associated with the purchase, either directly from the URL or +indirectly from an identifier in a database. Efficiently +reconstructing the contract entirely from the URL instead of using +costly database transactions can be important, as costly disk +operations for incomplete purchases make merchants more susceptible to +denial-of-service attacks from adversaries pretending to be customers. -% Say that this doesn't require accounts! -% explain that HTTP session state can be restored -% from the wallet state (replay!) +When a customer has completed a purchase, navigating to the +fulfillment URL in a browser will show the resource associated with +the purchase. This resource can be a digital good such as a news +article, or simply a confirmation for products that are delivered by +other means. -% explain repurchase correlation ID +When a customer has not yet completed a purchase (this is always the +case when a customer visits the fulfillment URL for the first time), +or when the Web shop cannot confirm that this visitor has paid for the +contract, for example because the session state was +lost,\footnote{This can happen when when privacy conscious users + delete their cookies. Also, some user agents (such as the TOR + browser) do not support persistent (non-session) cookies.} the Web +store responds by (again) triggering a payment process (either via +JavaScript or using {\tt 402 Payment Required}, see +Figure~\ref{listing:http-execute}). However, unlike the response from +the offer URL, the 402 response from the fulfillment page includes the +headers {\tt X-Taler-Contract-Hash}, {\tt X-Taler-Pay-Url} and {\tt + X-Taler-Offer-Url}. -% contract vs complete fulfillment URL +If the contract hash matches a payment which the user already +previously approved, the wallet reacts to this by injecting the logic +to transmit the payment to the {\em pay} URL of the Web shop into +the page. Then the wallet inspects the response as it may contain +error reports about a failed payment which the wallet has to handle. +By submitting the payment this way, we also ensure that this +intermediate request does not require JavaScript and still does not +interfer with navigation. Once the Web shop confirms the payment, the +wallet causes the fulfillment URL to be reloaded. -% design that allows merchant to not store any information - -A purchase by a customer, completed or in progress, is uniquely -identified by a URL, called the \emph{fulfillment URL}. The -information contained in the fulfillment URL must allow the merchant -to restore the full contract that was associated with the purchase, -either directly from the URL or indirectly from an identifier in a -database. Efficiently reconstructing the contract entirely from the -URL instead of using costly database transactions can be important, as -costly disk operations for incomplete purchases make merchants -more susceptible to denial-of-service attacks from adversaries -pretending to be customers. - -When a customer completed a purchase, navigating to the fulfillment -URL in a browser will show the resource associated with the purchase. -This resource can be a digital good such as a news article, or simply -a confirmation for products that are delivered by other means. - -% FIXME: maybe we should have the URL that we are requesting -% in the example, and not just the response? +If the contract hash does not match a payment which the user +already approved, for example because the user obtained the link +from another user, the wallet navigates to the offer URL included +in the header. \begin{figure*}[t!] \lstset{language={}} @@ -922,41 +933,7 @@ X-Taler-Offer-Url: https://shop/generate-contract/42 \label{listing:http-execute} \end{figure*} -In order to ensure that only the paying customer has access to the Web -resources behind the fulfillment URL, the Web store's server must -check the browser's session state. If the merchant can confirm that -the visitor has paid, the respective Web resource is returned. If the -merchant cannot confirm that the visitor has paid for the contract, -for example because the session state was lost,\footnote{This can - happen when when privacy conscious users delete their cookies. - Also, some user agents (such as the TOR browser) do not support - persistent (non-session) cookies.} it {\em again} triggers a payment -process (either via JavaScript or using {\tt 402 Payment Required}, see Figure~\ref{listing:http-execute}). -Since the fulfillment URL refers to a contract that typically is already known -to the user's wallet, it suffices to pass the contract hash (instead of -full contract) to the wallet. -If the user previously approved paying for the contract with this hash, the -wallet will (re-)transmit the signed coins that are associated -with the contract to the merchant. - -When a user visits a fulfillment URL without having the associated -contract in their wallet, the wallet redirects the browser to the {\em - offer} URL for that purchase, if applicable. This behavior is -useful when a user wishes to share a fulfillment link with another -user to point him to the same resource. - -Note that due to the limited WebExtensions API, the session state can -only be acquired when the wallet causes the browser to navigate to the -fulfillment URL (first without session state), since the session state -must be set from the same origin as the fulfillment URL. As a result, -the shop cannot simply return the fulfillment information in response -to the wallet performing the payment. However, this extra round trip -is also justified as the wallet needs to inspect the response anyway -as it may contain error reports about a failed payment which the wallet -has to handle. Finally, it ensures that the fulfillment page is fetched -via an HTTP GET request instead of an HTTP POST request, which is -important to nicely support the use of navigation (``back'', ``forward'' -buttons) and bookmarks. +\subsubsection{Discussion} Various failure modes are considered in this design: