That’s not my intention, but I wanted to have some “sane defaults” that allows us to spec something simple but extensible.
A future update might allow the requestor so specify alternative bilateral protocols but for now this “none specified” = “ILP over HTTP”.
I don’t think so. If we define an API (using Swagger or Open API or similar) then it is a set of resource paths relative to some base.
An alternative could be to define a standard response to a GET at the base that provides those details? See revised proposal below.
I don’t think JWT Bearer is hard. It’s already implemented in the JS and Java ILP over HTTP implementations, and it’s solving a lot of other issues with auth (like identifying the subject) as @sappenin points out.
Simple shared secret is a bad auth protocol IMO because it makes assumptions about the competency of the participants to manage lifecycle etc.
I’d prefer to say JWT’s are the default standard but leave it open for people to specify others (ideally from the list of widely used schemes in the Open API 3.0 spec not "roll-your-own"s.
Assets
Based on discussion so far I’d also propose we drop any data exchange around assets and assume that if you are auto-peering you are going to be the child and the server will be the parent.
Let’s keep this focused on:
- discovering the bilateral protocols the server supports
- requesting to peer with the server
- getting authentication credentials to use with one of the available bilateral protocols
- creating the bilateral connection
Once this is complete the peers can exchange ILP packets to setup settlement (and by implication determine the underlying asset).
This does raise some questions:
- What if you peer with someone, only to discover they don’t offer settlement in the asset or using the settlement protocol you want?
- Is there a benefit to the server, when it issues you credentials, in knowing what asset you plan to transact in?
Proposal 2
Alice sets up her connector at https://alice.example
and configures it to peer with Bob at https://bob.example
.
- Alice’s connector makes a GET request to
https://bob.example
and get’s back an Open API 3 specification in JSON format, something like:
{
"openapi": "3.0.2",
"info": {
"version": "1.0.0"
},
"paths": {
"/register": {
"post": {
"operationId": "registerPeer",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Peer"
}
}
}
}
}
},
"/ilp": {
"post": {
"operationId": "receiveIlpPrepare",
"security": [
{
"jwt-bearer-token": []
}
]
}
}
},
"components": {
"securitySchemes": {
"jwt-bearer-token": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "jwt"
},
"api-key": {
"type": "apiKey",
"in": "header",
"name": "X-API-KEY"
}
}
}
}
This is a standard Open API v3 schema, trimmed down to only provide the paths and security schemes. If we standardise on the operationId
then you can map it to whatever path you want.
Pros: This is a well-supported standard for defining APIs and provides a lot of flexibility.
Cons: Seems way over complicated for our needs. (We could define this API using Open API v3 once and just get all servers to implement it at using a standard base.) It also provides no info on settlement options.
Let’s imagine a simpler return value from the GET
request to the base URL:
{
"ilp": {
"http": {
"version": "1.0",
"url": "https://bob.example/ilp-service", // Default to /ilp but allow for custom
"security": [ "jwt-bearer-token" ]
},
"btp": {
"version": "1.0",
"url": "wss://bob.example/btp",
"security": [ "jwt-bearer-token" ]
}
},
"settlement": {
"XRP": [ "xrp-paychan", "xrp-ledger"],
"BTC": ["lightning"]
}
}
- Alice’s connector makes a POST request to
https://bob.example/register
with the payload:
{
"ilp": {
"http": {
"version": "1.0",
"url": "https://alice.example/ilp",
"security": {
"jwt-bearer-token": {
"iss": ["*"], //List of issuers Alice will allow. "*" for any
"sub": "bob" //Subject Bob must use
"aud": "https://alice.example"
}
}
},
},
"settlement": {
"XRP": ["xrp-paychan"] // Alice will settle using XRP Paychan
}
}
- Bob sets Alice up as a child peer on his system and responds with:
{
"ilp": {
"http": {
"version": "1.0",
"url": "https://alice.example/ilp",
"security": {
"jwt-bearer-token": {
"secret": "uywdf66rFGFd8u==" //Secret to use to sign JWT
"iss": ["https:/alice.example"], //List of issuers Bob will allow.
"sub": "alice-xrp" //Subject Alice must use
"aud": "https://bob.example"
}
}
},
}
- Alice sends her first packet to
https://bob.example/ilp
The request contains anAuthorization: Bearer XXXX
header whereXXXX
is a JWT created by Alice.
The JWT uses the HMAC256 signing algorithm and has at least the following claims:
- the subject (
sub
):alice-xrp
- the issuer (
iss
):https://alice.example
- the audience (
aud
):https://bob.example
The first packet will likely be a peer.settle.config
request to get her settlement arrangement setup (details still being figured out but discussion started here )
-
After getting a settlement configured Alice sends an IL-DCP request to get her address and find out what scale she must use in ILP packets.
-
Alice receives payments from Bob when Bob sends packets to Alice. These are sent by Bob to
https://alice.example/ilp
also using JWT bearer tokens. In this case the claims in the the token are:
- the subject (
sub
):bob
- the issuer (
iss
):https://bob.example
- the audience (
aud
):https://alice.example