breez / breezmobile

Lightning Network mobile client
https://breez.technology
GNU General Public License v3.0
566 stars 129 forks source link

[Podcast] Add support for LSAT for HTTP requests #1010

Open bumi opened 1 year ago

bumi commented 1 year ago

LSAT is a HTTP based authentication scheme that defines a protocol to exchange lightning payment information on the HTTP level. It is intended to communicate a payment request from the server to the client and to allow the client to authenticate requests using the lightning payment information (preimage).

Thanks to the protocol client and server do not need to know of each other before the request and payments an be incorporated in the HTTP request flow (for the feed and episode files)

This protocol fits perfectly for the podcasting world where a player talks to various hosters and requests the feed and the episode files through HTTP.

Adding support for LSAT gives podcasters an additional monetization option. It is an open, flexible alternative for example for some podcasters publishing special episodes on tools like patreon or provide special private RSS feeds to a paying user community. Using LSAT this can be handled with the normal feed and gives the user the choice within the player (no need to go to third-party apps like Patreon before hand)

Simple example flow (sorry for the lazy diagram):

(user could configure to prefer the payment authenticate content per podcast or globally) client ---> HTTP request indicating LSAT support ----> server client <--- 402 status code with a payment request <--- server (user could be prompted here, or a config option could allow auto payments like in the streams) client ---> HTTP request with payment proof ---> server client <--- actual requested resource <--- server (client stores the authentication details for future requests)

If a client does not support LSAT the server simply returns the public response, but if the client supports LSAT (indicating this with the Accept-Authenticate: LSAT HTTP header) the server returns an authenticate response.

Here is an example JavaScript implementation to handle the LSAT handshake with fetch() and use webln to send the payment: https://github.com/getAlby/alby-tools/blob/master/src/lsat/fetch.js

Open for discussion:

Links

kingonly commented 1 year ago

Thanks for opening the issue @bumi 🙏 In order to implement it for podcasting, I believe we need some kind of marker in the splits (to know which payment proof to send), right?

bumi commented 1 year ago

I think this must work without any adjustment on the value tag. Initially I thought of it completely independent (and it could be independent). Can we assume that whoever hosts the feed/episode also knows about the splits? And I can not wrap my head around the keysend based verification right now, can you mention again your thoughts there?

(with an invoice the server would typically simply check the payment hash and does not need a node connection.)

kingonly commented 1 year ago

My idea is simple: keysend works (at least in lnd, need to verify cln) by creating an invoice on-the-fly. It returns a preimage. We need to use the preimage that keysend returns and send it back in LSAT. However, we need to know which preimage from the splits to use, hence - a need for a marker in the split. Just an optional tag on one of the splits will do. It's backward compatible and shouldn't break anything.

bumi commented 1 year ago

What will the server use to lookup the invoice and validate the payment?

(The nice thing about the invoice is that the server does not need to connect to a node to do the validation - the preimage + the payment hash from the invoice is enough)

kingonly commented 1 year ago

There's still a preimage. The only difference from a regular invoice is that the invoice is created on-the-fly when the payee receives the keysend. If you don't want to ask the node to validate, I can think of several solutions like sharing the hashes with the server prior to the payment or at settlement.

adamc199 commented 1 year ago
kiwiidb commented 1 year ago

Which hash would the server use in the macaroon in the first step of the LSAT handshake? Would it need to return a macaroon at all, or would the first step even be skipped completely? Would the client just request the file with the preimage in the header without any macaroon?

My main problem with trying to make keysend fit into LSAT we would be throwing away the central idea of LSAT, namely the cryptographic link between invoice and macaroon.

kingonly commented 1 year ago

The LSAT can contain the specific split that should be used. It's not really trying to make keysend fit rather trying to keep the splits. The client understand which split they should reference from the LSAT, they make the keysend, get the preimage and send it back. I think it works nicely, nothing added to the value block, and even maintains the WWW-Authenticate semantics imo.

kiwiidb commented 1 year ago

But which hash should the server use in the macaroon? See https://lsat.tech/macaroons . Using keysend would throw away the central idea of LSAT. Screenshot 2022-12-19 at 09 14 44

The server would also need to store state to keep track of which preimages have been used for which files and check each request against this database, a pretty ugly setup in my eyes.

kingonly commented 1 year ago

Why does the server need a state? It can just delegate the validation to the node. Don't get wrong, I understand what's bothering you, but I thought the requirement here is to support the splits and the value block w/o making changes to it.

kiwiidb commented 1 year ago

lsat-flow

I have attached a diagram that can illustrate how we could change the flow to support keysend payments. Instead of an invoice the first call would return the node id for which the client would need to send over payment "proof" in the second part of the handshake. The macaroon in the first step would also not contain a payment hash.

For the client there wouldn't be that many differences, however the validating server would need to hash the preimage and then look up the payment with the node using the payment hash.

kingonly commented 1 year ago

LGTM!

  1. Would you return the amount alongside the node id? Does the amount represents the amount to be sent to the specific node id or the expected total amount? I think it should represent the minimum amount to be sent to the specific node.
  2. Does it matter if the node id appears more than once ain the splits? Maybe we should should choose the highest split in this case?