[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Taler] transaction history UX and fulfillment URL semantics

From: Christian Grothoff
Subject: Re: [Taler] transaction history UX and fulfillment URL semantics
Date: Mon, 25 Jan 2016 08:03:31 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Icedove/38.5.0

On 01/24/2016 11:24 PM, Florian Dold wrote:
> On 01/24/2016 10:40 PM, Christian Grothoff wrote:
>> On 01/24/2016 09:35 PM, Florian Dold wrote: 
>> Again, I thought you argued nicely for cookie-state to be disallowed.
>> Also, AFAIK /contract was never expected to do much on the session
>> management side, it was just supposed to return the JSON-formatted
>> signed contract.
> I really *wish* we could eliminate session state, but then we would have
> to ditch PHP session management, and cookie-based session management in
> other common frameworks as well.
> And yes, I always argued against session state, but your argument that
> it makes it easier for merchant implementations was rather convincing ;-)
> So, at this point we should make a definite decision to support session
> state or not, because it influences the rest of the design a lot.

Well, I think we can "support" cookies by having the teaser or
fulfillment page (on failure) set them just before interacting with the
wallet.  The wallet doesn't keep them as part of its state, so if I go
back to the fulfillment page via the list of contracts, it is possible
that the cookie is gone, just like when I shared the link. But then we
simply again get a fresh cookie and go the "long" route via the wallet
POSTing /pay and after the /pay -> fulfillment redirect the cookie
should then be preserved.

In other words, the Wallet doesn't really do anything with cookies, but
the design inherently allows their use, which seems reasonable.

>> I thought we decided cookies were bad.  If the UUID is OK as-is (refers
>> to a paid contract, and if the payment is tied to an IP address, the
>> client's IP is unchanged), then we execute. Now, cookies could
>> optionally be used as well, but I'm not sure "in most cases" is the
>> preferred formulation.
> Okay, maybe I missed the point of our earlier discussion then.  I
> thought you were arguing in favor of cookies that can be restored by
> going to a special page?
> I don't see why we would ever want to tie a contract UUID to an IP
> address though.  This is really bad, today people are in environments
> where their IP address changes all the time (if I move a bit to the
> side, my phone / laptop might connect to a different WiFi hot spot).
> I'm strongly against this ...
>>> * otherwise asks the wallet to execute the contract that is associated
>>> with the URL (i.e. serves as the execution page to inject the request in
>>> the right domain context)
>> I'd have described this differently: The merchant generates a page that
>> interacts with the wallet to trigger the payment dialog.  For this, the
>> merchant frontend may internally fetch /contract and inline that, or
>> send JS to the browser where the JS then (as usual) fetches the
>> /contract page. The page may set a cookie (see above). In either case,
>> we directly interact with the wallet and effectively ask the wallet
>> would still ask the wallet to issue a POST to /pay.  The wallet can use
>> the contract-UUID to detect that it already paid on this very contract
>> and just auto-replay an old /pay (resulting in the browser being
>> redirected to a now valid fulfillment, see first case), or if this is a
>> "first-time" contract, interactively prompt the user to approve it (same
>> as after "checkout" in shopping cart).
> Yes.  You're describing exactly what I meant to say :-)
>>> * if this fails (the wallet does not have the contract) it redirects the
>>> user agent to a page where the user can buy the product, since the user
>>> must have gotten the link from somewhere without having bought the product.
>> Your formulation is unclear here. In particular, you write "it
>> redirects", but who is "it"?  "it" must not be the merchant's JS, as the
>> merchant's JS must not be able to learn which contracts our wallet has
>> executed already.  The merchant's JS is always doing just one thing: ask
>> the wallet to pay for a contract. Thus, the wallet should be the "it"
>> that makes a choice here.
> This is a bit tricky, since if we go to a fulfillment page that we got
> from a friend via email (where we didn't pay for it ourselves), the
> merchant needs to let the wallet know where to get the contract to buy
> e.g. the article.
> This inherently allows the merchant to know whether the user paid for
> THIS contract UUID from THIS merchant (the matching is done based on the
> fulfillment URL including the UUID), which is reasonable enough.

Not exactly, as after presenting the contract to the wallet, there are
two possible outcomes: nothing happens, or the user pays. If nothing
happens, the merchant doesn't know if the user navigated away (aborted
payment) or not. If pay happens, the merchant can tell if it was the
'same' user (replay of payment) or a fresh one, and that's acceptable
because that user probably is OK with the merchant knowing that he's the
very same user visiting the very same document again to avoid paying

The really ultra-paranoid version would be disable this replay of an
existing payment and to ask the user if he wants to pay *again* to
ensure that his two visits to the same resource are unlinkable.  Now,
just to be clear: that may be an advanced wallet option in the future,
but I'm not advocating for ultra-paranoid for now. But I am arguing for
super-paranoid (see below).

>> Also, your formulation is unclear as to what it means to "redirect the
>> user agent".  The wallet may move the browser to a wallet-controlled
>> backend-page showing the contract (where the user can accept/reject).
>> The wallet should not redirect the user agent to some other "shopping"
>> page generated by the merchant's frontend.
> Why not?  If I send you the fulfillment link for an article I paid, you
> should be redirected to the teaser page with the "buy this" link for the
> article.  Again, the information the merchant can gain is negligible,
> and the alternative would be to just say "oh, this is not yours, but we
> won't tell you what it is either".

For me, the contract itself -- and the fact that I'm following a link
presumably for a reason serve as the "teaser" in this case.  Otherwise
the wallet would leak information in a way that is inacceptable to me.

> A super paranoid wallet could ask the question "do you want to go to the
> checkout page for this contract, since it's not in your wallet", and
> then the merchant can't distinguish between customers who already have
> the article and those who just didn't bother buying it.

Yep, having this "super paranoid" wallet is exactly what I'm suggesting.

>> What is your notion of equivalence here? And which URL? If we (still)
>> have /contract, /pay (POST), and /fulfillment, the 'replay' may _look_
>> the same for the customer for the /fulfillment in my interpretation of
>> the design. The customer also never sees /contract and /pay URIs, but
>> they still exist internally. Also, the replay is technically still very
>> different, as in some cases (cookie/state OK) we immediately deliver the
>> information, while in others (no cookie/state bad/payment failed
>> earlier) we have like 3 additional round-trips with requests to /pay
>> before the content is finally transmitted.  Now, again this may happen
>> behind the scenes and thus (more or less) invisible to the customer, but
>> it's not exactly "equivalent".
> "Equivalent" in the sense that the browser makes the same request.
> Why would "replay" from the wallet do anything different then just open
> the fulfillment URL in a new tab, which then does the steps we discussed
> above?
> This is not even a premature optimization; why should we have two
> different implementations here when one is enough?

That is true, the implementation would be the same. My point was that
depending on the browser's state (paid, not paid, cookie present, cookie
failure) different things actually happen next.

> Why would I ever want to do a replay if the UUID-based fulfillment link
> just gives me what I want?
>> If this is about combining /exec and /pay, I'm fine with that. The
>> result is nice in that there is only one visible URI to the customer
>> (the /fulfillment URI). Still, having the POST /pay separate is IMO the
>> right thing, as is having an (optional) GET /contract URI.
> Yeah, I never wanted to eliminate /pay. And /contract is a merchant
> implementation detail, it should not be in the HTTP API spec but in the
> reference implementation docs.


Attachment: signature.asc
Description: OpenPGP digital signature

reply via email to

[Prev in Thread] Current Thread [Next in Thread]