Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated HTTP-ILP (Continuation of #149) #306

Merged
merged 8 commits into from
Oct 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 144 additions & 0 deletions 0014-http-ilp/0014-http-ilp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
---
title: HTTP-ILP
draft: 1
---
# HTTP-ILP

> A standard for paid HTTP requests.

# Design Goals

Design a protocol to pay for HTTP requests.

Criteria:

* Minimum number of roundtrips
* Interaction with HTTP server is via HTTP (actually HTTPS) calls only - we want to tie into the existing load balancing and security infrastructure (HTTPS), no need to run any JavaScript/Websocket client on the HTTP server or other shenanigans

# Flows

## 1. Setup

###### Scenario

**Ankita** is a *server admin* who owns a file hosting service at `myservice.example` and would like to provide an API where her users can upload files without having to register first. In order to enable this in a standards-compliant way, she decides to use HTTP-ILP.

### 1.1. Server admin installs an ILP payment module

After deciding to use HTTP-ILP, Ankita searches the web on instructions on how to set this up. She finds an open-source HTTP-ILP server module which is compatible with the REST framework ([Koa](https://koajs.com)) that she is already using, for instance [koa-ilp](https://github.com/justmoon/koa-ilp).

She installs the HTTP-ILP server module. The module provides middleware which she adds to the different API endpoints in order to set prices for each one.

According to the documentation of the HTTP-ILP server module, she learns that she can pass an [Interledgerjs plugin](../0004-ledger-plugin-interface/0004-ledger-plugin-interface.md) to the module, to receive payments.

### 1.2. Server admin sets up a new receiver


Ankita creates a dedicated subaccount under her account at her Interledger service provider, and takes a note of that subaccount's credentials.

### 1.3. Server admin enters credentials into the HTTP-ILP server module config

Next, Ankita logs back into her server and edits a config file of the HTTP-ILP server module to enter the plugin type and credentials she obtained:

```sh
export PLUGIN_NAME=ilp-plugin-btp-client
export PLUGIN_CONFIG={"server":"btp+wss://ankita+filepay:fxPERNaS4FGlC8H7eg6UfYVlglmFynFc8nh5la9PBGM@nexus.justmoon.com"}
```

Next, she restarts her server to load the new configuration.

### 1.4. Paid HTTP server fetches receiver information

When the HTTP-ILP server module loads up, it calls [plugin#connect](../0004-ledger-plugin-interface/0004-ledger-plugin-interface.md#connect) so that the plugin
gets a subscription to its ledger. Through this subscription, the plugin can listen for incoming payments.
The module then uses [plugin#getAccount](../0004-ledger-plugin-interface/0004-ledger-plugin-interface.md#getaccount) to look up the Interledger address from the plugin
and caches it in memory for a certain period.

This completes the setup process. The server is now ready to receive paid API requests.

## 2. Client interaction

###### Scenario

**Marat** is a *graphic designer* who would like to upload a mockup image to share with a client. His friend recommended a tool which doesn't require any signup or configuration and uses his existing ILP account to pay for the storage and bandwidth fees.

![Sequence Diagram](sequence.png)

### 2.1. Client generates a server-specific token from the hostname and its local secret:

The uploader tool contains an HTTP-ILP client module
like [superagent-ilp](https://github.com/justmoon/superagent-ilp) or [ilp-curl](https://github.com/sharafian/ilp-curl).
This client module may for instance generate and locally save a `client_secret` using 256 bits of cryptographically secure randomness.

Before making the paid HTTP request, the HTTP-ILP client module generates a **token**, for instance using such a `client_secret` and the `hostname` of the server it is about to make a request to:

* Token: `HMAC(SHA256, client_secret, hostname)`

### 2.1. Client attempts to call API using token

The paid HTTP request is fired off:

``` http
OPTIONS /upload HTTP/1.1
Host: myservice.example
Pay-Token: 7y0SfeN7lCuq0GFF5UsMYZofIjJ7LrvPvsePVWSv450
Unhash-Content-Length: 123
```

Note that the client hasn't paid at this point and is only making the request to solicit a response from the server, that's why the OPTIONS verb is used. In this example,
`Unhash-Content-Length` is an application-specific header which describes the request which the client intends to make.

### 2.2. Server responds with payment details

The server returns an HTTP code of `204 No Content` and includes response headers showing the amount, an ILP address and a shared secret.
The amount expresses how much the request would have cost, as a decimal string and counted in the base unit of the ledger to which the ILP address belongs.

``` http
HTTP/1.1 204 No Content
Pay: 10 us.nexus.ankita.~recv.filepay SkTcFTZCBKgP6A6QOUVcwWCCgYIP4rJPHlIzreavHdU
Pay-Balance: 0
```

The client can now use the shared secret to create a condition to pay this host. The shared secret may for instance be generated by the server as follows:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should explain that the destinationAccount and sharedSecret are used as the parameters to PSK


* Shared Secret: `HMAC(SHA256, receiver_secret, token)`

The shared_secret is now a shared secret between the client and server, but will be unknown to any third-party connectors between them.

### 2.3. Client initiates an ILP payment to refill its balance

In order to refill its balance, the client now creates an ILP payment with the following properties:

* Destination: `us.nexus.ankita.~recv.filepay`
* Amount: `100`
* Condition: `SHA256(fulfillment)`
* Memo: `pay_token`

The `fulfillment` is generated from the shared secret using [PSK](../0016-pre-shared-key/0016-pre-shared-key.md).

When the prepared payment reaches the server, it is fulfilled and the token's balance is increased.

There is a chance that the HTTP-ILP server module will process the payment, but the fulfillment doesn't make it all the way back to the sender.

### 2.6. Sender/client receives the fulfillment.

Once the HTTP-ILP client module receives the fulfillment, it will now retry its original request:

``` http
POST /upload HTTP/1.1
Host: myservice.example
Pay-Token: 7y0SfeN7lCuq0GFF5UsMYZofIjJ7LrvPvsePVWSv450
```
```
[...]
```

The request succeeds:

``` http
HTTP/1.1 200 OK
Pay: 10 us.nexus.ankita.~recv.filepay SkTcFTZCBKgP6A6QOUVcwWCCgYIP4rJPHlIzreavHdU

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unhash might make a better example application, because we know exactly what the API calls look like for it. For instance, an Unhash OPTIONS request includes the Unhash-Content-Length header to calculate the price.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I'll add Unhash-Content-Length to the OPTIONS call and explain that other services would have other product descriptors which the client can add to help determine the price for a request.

Pay-Balance: 90
```

Notice how the 100 units credit from the payment was added to the balance and the 10 unit cost for the current request was subtracted.
29 changes: 29 additions & 0 deletions 0014-http-ilp/sequence.mmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
sequenceDiagram
participant Payer
participant Interledger
participant PayeeWallet
participant Payee
activate Payer
Payer->>+Payee: OPTIONS preflight
Payee-->>-Payer: 204 preflight response
Payer->>Interledger: Quote Request
activate Interledger
Interledger->>Payer: Quote Response
deactivate Interledger
Payer->>Interledger: Prepare Payment
activate Interledger
Interledger->>PayeeWallet: Prepare Payment
deactivate Interledger
activate PayeeWallet
PayeeWallet->>+Payee: Webhook Request
deactivate PayeeWallet
Payee-->>-PayeeWallet: Webhook Response
activate PayeeWallet
PayeeWallet-->>Interledger: Fulfill Payment
deactivate PayeeWallet
activate Interledger
Interledger-->>Payer: Payment Fulfilled
deactivate Interledger
Payer->>+Payee: POST Paid Request
Payee-->>-Payer: 200 OK
deactivate Payer
Binary file added 0014-http-ilp/sequence.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions 0014-http-ilp/sequence.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.