diff --git a/blip-0026.md b/blip-0026.md new file mode 100644 index 0000000..8ffe61d --- /dev/null +++ b/blip-0026.md @@ -0,0 +1,712 @@ +``` +bLIP: 26 +Title: L402: The Lightning HTTP 402 Protocol +Status: Active +Author: Olaoluwa Osuntokun + Oliver Gugger + Wilmer Paulino +Created: 2023-06-06 +License: CC0 +``` + +* [Abstract](#abstract) +* [Copyright](#copyright) +* [Motivation](#motivation) + * [The Forgotten HTTP Error Code](#the-forgotten-http-error-code) + * [Authentication and API Payments in a Lightning-Native Web](#authentication-and-api-payments-in-a-lightning-native-web) + * [HTTP + Macaroons + Lightning = L402](#http-+-macaroons-+-lightning-=-l402) + * [Example Applications and Use Cases](#example-applications-and-use-cases) +* [Rationale](#rationale) +* [Specification](#specification) + * [Authentication Flow](#authentication-flow) + * [Detailed authentication flow](#detailed-authentication-flow) + * [L402 HTTP/gRPC Protocol Specification](#l402-http/grpc-protocol-specification) + * [Reusing Credentials](#reusing-credentials) + * [Security Considerations](#security-considerations) + * [HTTP Specification](#http-specification) + * [gRPC Protocol Specification](#grpc-protocol-specification) + * [Macaroon Minting & Verification](#macaroon-minting-&-verification) +* [Macaroon Minting & Verification](#macaroon-minting-&-verification) + * [Minting Macaroons](#minting-macaroons) + * [Macaroon Identifier](#macaroon-identifier) + * [Attenuation Through Caveats](#attenuation-through-caveats) + * [Target Services](#target-services) + * [Service Capabilities](#service-capabilities) + * [Service Constraints](#service-constraints) + * [Macaroon Verification](#macaroon-verification) + * [Macaroon Revocation](#macaroon-revocation) +* [Universality](#universality) +* [Backwards Compatibility](#backwards-compatibility) +* [Reference Implementation](#reference-implementation) + +# Abstract + +L402 is a standard to support the use case of charging for services and +authenticating users in distributed networks. Developed by Lightning Labs, it +combines the strengths of Macaroons, for better authentication, and the +strengths of the Lightning Network, for better payments. L402 API credentials +invigorate the HTTP 402 Payment Required error code by combining the +fine-grained authentication capabilities of Macaroons with Lightning Network +payments, making it easy to charge amounts of any size for an API request, web +page or resource. + +An L402 key is created like a Macaroon. It combines the advantages of bearer +and identity-based authentication systems that can quickly be issued and +verified without requiring access to a central database. + +In addition to a regular Macaroon, an L402 includes a payment hash, which is +presented to the user with a Lightning Network invoice. The user can prove +their successful payment if the preimage matches the payment hash. + +A valid L402 key , meaning a Macaroon issued by the service and the preimage +obtained by the user, is easy to verify by distributed systems. Instead of +looking up cookies or payment details using centralized databases, an L402 key +can be verified using minimal information and basic cryptography. + +This system allows users to automate pricing on the fly and enables a number of +novel constructs such as automated tier upgrades. L402 get its name from the +HTTP status code 402: Payment Required. + +# Copyright + +This bLIP is licensed under the CC0 license. + +# Motivation + +In this document we aim to specify a protocol standard of what we call an +`L402`. `L402` is derived from HTTP status code 402: Payment Required. L402 is +a new standard protocol for authentication and paid APIs developed by Lightning +Labs. An L402 can serve both as authentication, as well as a payment mechanism +\(one can view it as a ticket\) for paid APIs. By leveraging L402, a service or +business is able to offer a new tier of paid APIs that sit between free, and +subscription: pay as you go. + +One can view L402 as a fancy authentication credential or cookie. They differ +from regular cookies in that they're a cryptographically verifiable bearer +credential. An L402 credential _encodes_ all its capabilities within a macaroon +which can only be created by the end service provider. The L402 specification +uses a combating of `HTTP` as well as the Lightning Network to create a +seamless end-to-end payment+authentication flow for the next-generation of paid +APIs built on top of the Lightning Network. + +The system described above isn't a fantasy, L402 is used _today_ by Lightning +Labs to serve as an authentication+payment solution for Lightning Loop, a +non-custodial on/off ramp for the Lightning Network and Lightning Pool, a +non-custodial market place for liquidity in the Lightning Network. Lightning +Labs, has also open sourced `aperture`, a reference L402 aware reverse-proxy +used in production for all our systems. In the remainder of this section, we'll +explore the motivation, lineage, and workflow of L402 at a high level. For a +more detailed speciation, please see the later sections of this specification. + +## The Forgotten HTTP Error Code + +HTTP as we know it today uses a number of _error_ codes to allow developers to +easily consume APIs created by service providers. As an example, the well known +`200 OK` error code indicates a successful HTTP response. The `401 +Unauthorized` is sent when a client attempts to access a page or resource that +requires authentication, and so on. A large number of other error code exist, +with some more commonly used than others. One error code which has widely been +underutilized is: `402 Payment Required`. As the name entails, this code is +returned when a client attempts to access a resource that they haven't _paid +for_ yet. In most versions of the HTTP specification, this code is marked as +being "reserved for future use". Many speculate that it was intended to be used +by some sort of digital cash or micropayment scheme, which didn't yet exist at +the time of the initial HTTP specification drafting. + +However, several decades later, we _do_ have a widely used digital cash system: +Bitcoin! On top of that, a new network oriented around micropayments has also +arisen: the Lightning Network. Early in the lifetime of Lightning Labs, we were +drawn to the potential for paid metered APIs enabled by the Lightning Network. +We'd solved the payment portion with LN itself, the next challenge was to +create a protocol that would be easy to drop into _existing_ APIs in an easy +and extensible manner. Our solution to this is the L402 protocol. + +## Authentication and API Payments in a Lightning-Native Web + +Lightning has the potential to serve as the de-facto payment method to access +services and resources on the web. In this new web, rather than a user being +tracked across the web with invisible pixels to serve invasive ads, or users +needing to give away their emails subjecting themselves to a lifetime of spam +and tracking, what if a user was able to _pay_ for a service and in the process +obtain a ticket/receipt which can be used for future authentication and access? + +In this new web, email addresses and passwords are a thing of the past. Instead +_cryptographic bearer credentials_ are purchased and presented by users to +access services and resources. In this new web, credit cards no longer serve as +a gatekeeper to all the amazing experiences that have been created. L402 +enables the creation of a new more global, more private, more developer +friendly web. + +At this point, curious users may be wondering: How would such a scheme work? +Are the payment and receipt steps atomic? Why can't a user just forge one of +these "tickets"? + +## HTTP + Macaroons + Lightning = L402 + +An L402 is essentially a ticket obtained over Lightning for a particular +service or resource. The ticket itself _encodes_ what resource it's able to +access. It can be copied, or given to a friend so they can access that same +resources. It can also be _attenuated_ to provide a friend access to a slightly +weaker version of that resource \(able to stream video at only 480p as an +example\). On the other end, services can mint special tickets for particular +users, rotate, upgrade, and even revoke the tickets. + +The tickets themselves are actually _macaroons_. Macaroons are a flexible +standard for API credentials which are already used by `lnd` as its default +authentication mechanism. The L402 protocol allows a user to _atomically_ +purchase one of these tickets for sats over the Lightning Network. Partial L402 +are served over HTTP \(or HTTP/2\) when a user attempts to access a resource +that requires payment \(`402 Payment Required`\) along with a Lightning +_invoice_. This _partial_ L402 can then be converted into a _complete_ L402 by +paying the invoice, and obtaining the payment pre-image \(the invoice pays to a +payment hash: `payment_hash = sha256(pre_image)`\). + +With proper integration at end clients, Lightning wallets, mobile application, +browsers \(and extensions\), the above flow has potential to be even more +seamless than the credit card flow users are accustomed to today. It's also +more _private_ as the server doesn't need to know _who_ paid for the ticket, +only that it was successfully paid for. + +## Example Applications and Use Cases + +The L402 standard enables a number of new use cases, pricing models, and +applications to be built, all using the Lightning Network as a primary money +rail. As the standard is also defined over _HTTP/2_, it can be naturally +extended to also support gating access to existing _gRPC_ services. This is +rather powerful as it enables a _strong decoupling_ of authentication+payment +logic from application logic. Today Lightning Loop uses L402s in this very +manner to provide a lightweight authentication mechanism for our users. + +As L402 leverages the Lightning Network for its payment capabilities, they also +enable the easy creation of _metered_ APIs. A metered API is one where the user +is able to pay for the target resource or service as they go rather than +needing to commit to a subscription up front. Developers can use L402 to create +applications that charge users on an on going basis for resources like compute +or disk space. If the user stops paying, then the resource can be suspended, +collected, and re-allocated for another paying user. Once again, as the +standard supports _gRPC_ which supports _bi directional streaming_ APIs, one +could even create a metered streaming video or audio service as well! + +Additionally, L402 also enables innovation at the API _architecture_ level. One +example is automated tier upgrades. Many APIs typically offer several tiers +which allow users to gain access to more or additional resources as they climb +up the ladder. Typically, a user must _manually_ navigate a web-page to request +an upgrade to a higher tier, or downgrade to a lower tier. With the L402 +standard, tier upgrades can easily be automated: the user hits a new endpoint +to obtain an _upgraded_ L402 which _encodes_ additional functionality or +increased resource access compared to the prior tier. Services can even +leverage L402 for A/B Testing by giving subsets of users a distinct L402 which +when submitted to the service, render a slightly different version of the +target resource or service. + + +# Rationale + +# Specification + +## Authentication Flow + +This section explains the high-level authentication flow from the perspective +of a user and their client software. + +The requirements from the user's point of view are simple: They want to be able +to use a service as frictionless as possible. They are perhaps used to the +concept of needing to obtain an API access key first in order to use a service, +but do not necessarily want to register an account with their personal +information to do so. + +A service using the L402 protocol supports exactly that requirement: The use of +an API key without the need for creating an account first. And because no +information needs to be input, the process of obtaining the API key can happen +transparently to the user, in the background. + +Whenever an L402-compatible client software connects to a server that uses the +protocol, it receives a prompt to pay an invoice over a very small amount \(a +few satoshis\). Once the client software pays that invoice \(which can happen +automatically if the amount does not exceed a user-defined threshold\), a valid +API key or authentication token can be constructed. That credential is stored +by the client's software and will be used for all future requests. + +### Detailed authentication flow + +The following steps describe the diagram further below. It is the flow of calls +that take place for a client software that wants to access a protected resource +that is secured by an authentication server. + +As an example, we will look at the `loopd` client that wants to do a loop out +swap with the Lightning Lab's loop server. + +**First time looping out**: + +1. A loop user wishes to perform a swap with the loop server. They type the + command `loop out ` and hit return. + +2. The `loopd` client program contacts the loop server to initiate the swap. + +3. The call from the client must always go through the authentication server + reverse proxy, which in this example is `aperture`. The authentication proxy + notices that the client didn't send an L402 and therefore cannot be granted + access to the loop server. + +4. `aperture` instructs its own `lnd` instance to create an invoice over a + small amount that is required to acquire a fresh credential. + +5. In addition to the invoice, `aperture` also creates a fresh access + credential that is tied to the invoice. The credential is cryptographically + constructed in a way that it is only valid once the invoice has been paid. + +6. The credential and the invoice are sent back to the client in the previously + unused HTTP header `402 Payment Required`. + +7. The `loopd` understands this returned error code, extracts the invoice from + it and automatically instructs its connected `lnd` instance to pay the + invoice. + +8. Paying the invoice results in the `loopd` client now possessing the + cryptographic proof of payment \(the pre-image\). This proof is stored in + the client's local storage, together with the access credential. + +9. The combination of the access credential and the pre-image yields a fully + valid L402 that can be cryptographically verified. + +10. The client now repeats the original request to the loop server, now + attaching the L402 to the request. + +11. The authentication server intercepts the request, extracts the L402 and + validates it. Because the L402 is valid, the request is forwarded to the + actual loop server that then initiates the swap. + +12. The answer of the swap server is returned to the client and the swap is now + initiated. + +13. The whole process is fully transparent to the user. The only thing they + might notice is a short delay of a few seconds on the first ever loop. Each + successive loop will use the same credential and will not be delayed at + all. + +![e2e flow sequence diagram](bip-00026/e2e-flow.png) + +**All further loops**: + +1. For every new request to the server, the client now automatically attaches + the credential that is stored locally. + +2. As long as the credential has not expired, the steps 9-13 above will be + followed. If/when the credential expires, the server will start over at + step 4 and instruct + the client to obtain a fresh credential. + + +## L402 HTTP/gRPC Protocol Specification + +This section defines the "L402" authentication scheme, which transmits +credentials as `:` pairs, where the preimage is encoded +as hex and the Macaroon is encoded as base64. Multiple Macaroons are base64 +encoded individually and listed comma separated before the colon. This scheme +is not considered to be a secure method of user authentication unless used in +conjunction with some external secure system such as TLS, as the Macaroon and +preimage are passed over the network as cleartext. + +The L402 authentication scheme is based on the model that the client needs to +authenticate itself with a Macaroon and invoice preimage for each backend +service it wants to access. The server will service the request only if it can +validate the Macaroon and preimage for the particular backend service +requested. + +The L402 authentication scheme utilizes the Authentication Framework specified +in [_RFC 7235_](https://tools.ietf.org/html/rfc7235) as follows. + +In challenges: the scheme name is "L402". Note that the scheme name is +case-insensitive. For credentials, the syntax is: + +`macaroons` → [_<base64 encoding>_](https://tools.ietf.org/html/rfc3548#section-3), comma separated if multiple Macaroons are present +`preimage` → [_<hex encoding>_](https://tools.ietf.org/html/rfc3548#section-6) +`token` → macaroons ":" preimage + +Specifically, the syntax for "token" specified above is used, which can be +considered comparable to the [_"token68" +syntax_](https://tools.ietf.org/html/rfc7235#section-2.1) used for HTTP basic +auth. + +### Reusing Credentials + +L402 is intended to be reused until they are revoked and the server issues a +new challenge in response to a client request containing a newly invalid L402. +Possible revocation conditions include: expiry date, exceeded N usages, volume +of usages in a certain time period necessitating a tier upgrade, and +potentially others \(discussed further in the higher-level design document\). + +L402 could be configured for use on a per-backend-service basis or for all +Lightning Labs services. I.e., it’s flexible whether an L402 could apply to +both the Bos score API _and_ a loop-in, or just one of them. This flexibility +is afforded because all services are going to be gated by the same L402 proxy, +which verifies all Macaroons for all backend services. + +### Security Considerations + +If a client’s L402 is intercepted by Mallory, which is possible if the +transmission is not encrypted in some way such as TLS, the L402 can be used by +Mallory and the L402 proxy would not be able to distinguish this usage as +illicit. + +L402 authentication is also vulnerable to spoofing by counterfeit servers. If a +client slightly mistypes the URL of a desired backend service, they become +vulnerable to spoofing attacks if connecting to a server that maliciously +stores their L402 and uses it for their own purposes. This attack could be +addressed by requiring the user of the L402 to have a specific IP address. +However, there are downsides to this approach; for example, if a user switches +WiFi networks, their credential becomes unusable. + +### HTTP Specification + +In this section, we specify the protocol for the HTTP portion of the L402 +proxy. + +Upon receipt of a request for a URI of an L402-proxied backend service that +lacks credentials or contains an L402 that is invalid or insufficient in some +way, the server should reply with a challenge using the 402 \(Payment +Required\) status code. **Officially, in the HTTP RFC documentation, status +code 402 is** [_**"reserved for future +use"**_](https://tools.ietf.org/html/rfc7231#section-6.5.2) **-- but this +document assumes the future has arrived.** + +Alongside the 402 status code, the server should specify the `WWW-Authenticate` +header \([_\[RFC7235\], Section +4.1_](https://tools.ietf.org/html/rfc7235#section-4.1)\) field to indicate the +L402 authentication scheme and the Macaroon needed for the client to form a +complete L402. + +For instance: + +```text + HTTP/1.1 402 Payment Required + +Date: Mon, 04 Feb 2014 16:50:53 GMT + +WWW-Authenticate: L402 macaroon="AGIAJEemVQUTEyNCR0exk7ek90Cg==", invoice="lnbc1500n1pw5kjhmpp5fu6xhthlt2vucmzkx6c7wtlh2r625r30cyjsfqhu8rsx4xpz5lwqdpa2fjkzep6yptksct5yp5hxgrrv96hx6twvusycn3qv9jx7ur5d9hkugr5dusx6cqzpgxqr23s79ruapxc4j5uskt4htly2salw4drq979d7rcela9wz02elhypmdzmzlnxuknpgfyfm86pntt8vvkvffma5qc9n50h4mvqhngadqy3ngqjcym5a" +``` + +where `"AGIAJEemVQUTEyNCR0exk7ek90Cg=="` is the Macaroon that the client must +include for each of its authorized requests and `"lnbc1500n1pw5kjhmpp..."` is +the invoice the client must pay to reveal the preimage that must be included +for each of its authorized requests. + +In other words, to receive authorization, the client: + +1. Pays the invoice from the server, thus revealing the invoice’s preimage +2. Constructs the L402 by concatenating the base64-encoded Macaroon\(s\), a single + + colon \(":"\), and the hex-encoded preimage. + +Since the Macaroon and the preimage are both binary data encoded in an ASCII +based format, there should be no problem with either containing control +characters or colons \(see "CTL" in [_Appendix B.1 of +\[RFC5234\]_](https://tools.ietf.org/html/rfc5234#appendix-B.1)\). If a user +provides a Macaroon or preimage containing any of these characters, this is to +be considered an invalid L402 and should result in a 402 and authentication +information as specified above. + +If a client wishes to send the Macaroon `"AGIAJEemVQUTEyNCR0exk7ek90Cg=="` +\(already base64-encoded by the server\) and the preimage +`"1234abcd1234abcd1234abcd"` \(already hex encoded by the payee's Lightning +node\), they would use the following header field: + +```text +Authorization: L402 AGIAJEemVQUTEyNCR0exk7ek90Cg==:1234abcd1234abcd1234abcd +``` + +### gRPC Protocol Specification + +This section defines the "L402" gRPC authentication scheme, which, similarly to +the HTTP version, transmits credentials as `:` pairs +where the preimage is encoded as hex and the Macaroon is encoded as base64. +Multiple Macaroons are base64 encoded individually and listed comma separated +before the colon. As above, this scheme is not considered to be a secure method +of user authentication unless used in conjunction with some external secure +system such as TLS, as the Macaroon and preimage are passed over the network as +cleartext. + +The L402 proxy will determine whether an incoming HTTP request is gRPC by +checking whether the Content-Type header begins with application/grpc, +therefore gRPC clients must set this header in all requests. + +Note that the L402 proxy must be HTTP/2 compatible to accommodate requests for +gRPC backend services, since the gRPC client expects to be talking to a server +that "speaks" HTTP/2. + +Upon receipt of a request for a URI of an L402-proxied backend service that +lacks L402 credentials, the server should reply with a challenge encoded in the +grpc-status-details-bin HTTP header as a serialized gRPC Status proto message, +to be deserialized on the client side. Once deserialized, the proto will look +roughly like this object: + +```javascript +{ + code: 402, + message: "missing L402", + details: { + type_url: "type.googleapis.com/google.rpc.QuotaFailure", + value: { + macaroon: "", + invoice: "" + } + } +} +``` + +Note that deserialization is language-dependent. In Go, it looks something like +this: + +```go +_, err := client.AccessBackendService(ctx, &pb.BackendServiceRequest{}) +If err != nil { + st, _ := status.FromError(err) + message := st.Message() // get message + code := st.Code() // get code + for _, detail := range st.Details() { + switch t := detail.(type) { + case *errdetails.QuotaFailure: + for _, violation := range t.GetViolations() { + // parse macaroon from "macaroon:<mac>" format + // parse invoice from "invoice:<inv>" format +… +``` + +Serialization is similarly language-dependent. + +Depending on the context, QuotaFailure may not be the most descriptive error +message, but it fits a scenario where a user has exceeded their free "trial +period" for a backend service. + +Alongside the serialized status details, the server should specify status code +`200 OK`, the `Content-Type` header, and the following trailers: `grpc-message` +and `grpc-status`. + +For instance: + +```text +HTTP/2 200 OK +Date: Mon, 04 Feb 2014 16:50:53 GMT +Content-Type: application/grpc +… +Grpc-Message: missing L402 +Grpc-Status: 402 +Grpc-Status-Details-Bin: CJIDEgxtaXNzaW5nIExTQVQaeQ… +``` + +Where `"CJIDEgxtaXNzaW5nIExTQVQaeQ…"` is the serialized gRPC status proto. + +Once the client has deserialized the proto and extracted the Macaroon and +invoice, they may pay the invoice and construct the L402 identically to the +HTTP specification, i.e. by concatenating the base64-encoded Macaroon, a single +colon \(":"\), and the hex-encoded preimage. + +If a client wishes to send the Macaroon `"AGIAJEemVQUTEyNCR0exk7ek90Cg=="` +\(already base64-encoded by the server\) and the preimage +`"1234abcd1234abcd1234abcd"` \(already hex encoded by the payee's Lightning +node\), they would use the following header field: + +```text +Authorization: L402 AGIAJEemVQUTEyNCR0exk7ek90Cg==:1234abcd1234abcd1234abcd +``` + +Note this is the same as the HTTP specification. Other gRPC headers and +trailers are required; more information can be found in the [_gRPC over HTTP2 +specification_](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md). + + +## Macaroon Minting & Verification + +# Macaroon Minting & Verification + +In this section, we outline the specification of the Macaroon component of a +Lightning API key \(L402\). To recap, an L402 is composed of a Macaroon, which +specifies the allowed capabilities of the credential, and a preimage, which +serves as the credential’s proof of payment. Macaroons are perfect candidates +for L402 as they are tamper-proof, support easy rotation, have attributes, and +can even be further attenuated in order for applications that integrate an L402 +enabled service to delegate any additional capabilities. We’ll cover how +Macaroons are created, attenuated, and verified as part of L402. This chapter +will require an understanding of how Macaroons work and how they are useful in +the context of authentication. It may be useful to skim the [introductory +research paper on Macaroons](https://research.google/pubs/pub41892/). + +## Minting Macaroons + +Macaroons have three basic components: a public identifier that maps to a root +key, a list of caveats \(which is how attenuation is achieved\), and a +signature. Minting a new Macaroon only requires the public identifier and the +root key it corresponds to. + +Each Macaroon must have its own cryptographically random root key that must not +be disclosed to prevent forgeability of Macaroons. Each root key consists of 32 +bytes, which provides a reasonable tradeoff between entropy and size. Root keys +are essential to the verification of Macaroons, so they must be stored securely +and reliably. + +### Macaroon Identifier + +The key mapping to the secret is the SHA-256 hash of the Macaroon’s public +identifier, which contains static information about the Macaroon itself. In the +initial construction, the public identifier should include the following in the +listed order: + +> Note: All data specified here are encoded in big-endian unless otherwise +> stated. + +* **Version** - A version allows for an iterative Macaroon design. It must be + encoded in 2 bytes unsigned integer. +* **Payment Hash** - A payment hash links an invoice’s payment request to the + Macaroon. Once the payment request is fulfilled, the payer receives its + corresponding preimage as proof of payment. This proof can then be provided + along with the Macaroon to ensure an L402 has been paid for without checking + whether the invoice has been fulfilled. +* **User Identifier** - A unique user identifier allows services to track users + across distinct Macaroons serving useful in the context of service level + metering. A user identifier of 32 random bytes is used instead of the + macaroon's identifier because the latter can be revoked, e.g., in the case of + a service tier upgrade. + + +### Attenuation Through Caveats + +Caveats are predicates that restrict a Macaroon’s authority, as well as the +context in which it may be successfully used. When verifying a Macaroon, each +caveat predicate must be evaluated and hold true. Due to their flexibility, +additional context found within the request to a service may be necessary for +proper evaluation. + +Caveats of a version 0 Macaroon are represented as key-value pairs encoded as a +string where the key and value are separated by a single `=` character. The key +uniquely identifies a caveat and provides context as to how it should be +evaluated, while the value provides context for the evaluation itself. There +aren't any further restrictions on how caveats should be formed, but Lightning +Labs services will mostly impose three types of caveats which are covered +below. + +#### Target Services + +The target services the Macaroon is allowed to access is represented as a +caveat. The caveat key is `services`, while the value consists of a +comma-separated list of target services. Each target service is composed of a +two-tuple consisting of the service name and its tier. Tiers are service +specific and must start from 0, which serves as the base tier. If a specific +service tier has its capabilities and/or constraints updated, there needs to be +a way to detect when a Macaroon of the same tier with the now outdated +capabilities and/or constraints is being used. By committing to the service +tier, it is possible to detect such cases and seamlessly upgrade the stale +Macaroon \(assuming it is valid\) by revoking it and minting a new Macaroon +with the newer capabilities and/or constraints. + +When verifying this caveat, if a Macaroon is attempting to access a service +that it does not commit to, then it should be considered invalid. If multiple +services caveats exist, then verification should ensure each occurrence of the +caveat restricts more access than the previous. + +#### Service Capabilities + +Each service can further be restricted by the capabilities the service provides +and these are also represented as another caveat. These caveats have a key +ending in `_capabilities` that is prefixed with the service name, while the +value consists of a comma-separated list of the allowed service capabilities. +This type of caveat allows certain Macaroons to only have access to a subset of +a service's features. + +If a capabilities caveat for a particular service is not present, then the +Macaroon is able to access any capability of the service. If multiple +capabilities caveats exist for the same service, then verification should +ensure each occurrence of the caveat restricts more access than the previous. + +#### Service Constraints + +Each service can define its own set of constraint caveats for a given tier to +further restrict the capabilities of a Macaroon. Each constraint takes the form +of a caveat, where the key is prefixed with the service capability it applies +to, and the remainder of the key includes context for the service on how to +evaluate the constraint. The caveat value specifies the parameters for the +constraint evaluation. + +If multiple caveats of the same constraint are found within a Macaroon, then +verification should ensure each occurrence of the constraint restricts more +access than the previous. + +As an example, a base tier Lightning Loop Macaroon with access to a 2 BTC +monthly volume for Loop Out and unlimited volume for Loop In would look like: + +```text +identifier: + version = 0 + user_id = fed74b3ef24820f440601eff5bfb42bef4d615c4948cec8aca3cb15bd23f1013 + payment_hash = 163102a9c88fa4ec9ac9937b6f070bc3e27249a81ad7a05f398ac5d7d16f7bea +caveats: + services = lightning_loop:0 + lightning_loop_capabilities = loop_out,loop_in + loop_out_monthly_volume_sats = 200000000 +``` + +Due to the flexibility of the design, a Macaroon holder is able to further +attenuate a Macaroon if they wish to share it with a third party under more +restrictive permissions. Following the example above, the Macaroon holder can +restrict the Macaroon’s capabilities to only allow access to Loop In \(and not +Loop Out\) with a monthly volume of 1 BTC by adding the following caveats: + +```text +lightning_loop_capabilities = loop_in +loop_in_monthly_volume_sats = 100000000 +``` + +### Macaroon Verification + +Verifying a Macaroon consists of a three step process and involves two parties: +the minter of the Macaroon and the authorizer, which is the service the +Macaroon targets. The minter of the Macaroon performs signature checks to +ensure the Macaroon is valid, while the authorizer ensures the Macaroon has the +required permissions to access the service. + +The first step ensures a Macaroon was minted by the minter and it has not been +tampered with. This is done by computing the HMAC chain of the Macaroon, +starting from its root key and identifier, and including any further +attenuation through its caveats to arrive at the terminal signature of the +Macaroon. If these do not match, the Macaroon is invalid. If there isn’t a +valid root key corresponding to the Macaroon, it is also considered invalid. + +The second step ensures a Macaroon has provided a valid proof of payment +\(preimage\) and is performed by the minter as well. Since Macaroons commit to +the payment hash of an invoice, this is a trivial step. + +The final step ensures a Macaroon is authorized to access a service. This is +done by ensuring the service-specific caveat predicates of a Macaroon hold true +for the service being accessed. If only one of these caveats doesn’t hold true, +then the Macaroon is invalid. In the case of an unknown caveat, its evaluation +must be skipped by the authorizer as the Macaroon holder can further attenuate +the Macaroon for other applications. + +### Macaroon Revocation + +To prevent abusers of a Macaroon-based authenticated service, a Macaroon should +be able to be revoked. This can be achieved by having the minter remove the +Macaroon’s corresponding root key. By doing so, the minter will never be able +to verify the signature of a revoked Macaroon, ensuring it will never reach its +targeted service. + +Revocation also serves useful when performing a service tier upgrade on a +Macaroon. The prior Macaroon is revoked to ensure only the upgraded one can be +used going forward. + +# Universality + +# Backwards Compatibility + +The `L402` protocol was formerly known as `LSAT`. In order to preserve +backwards compatibility with clients, anywhere `L402` is used within HTTP +headers or requests, a valid protocol flow with the string `LSAT` should also +be accepted. + + +# Reference Implementation + +* [Aperture: A gRPC/HTTP authentication reverse proxy using L402s](https://github.com/lightninglabs/aperture) + +* [A utility library for working with L402s](https://github.com/Tierion/lsat-js) + +* [boltwall: Nodejs middleware-based authentication using L402s](https://github.com/tierion/boltwall) diff --git a/blip-0026/e2e-flow.plantuml b/blip-0026/e2e-flow.plantuml new file mode 100644 index 0000000..aa9cde8 --- /dev/null +++ b/blip-0026/e2e-flow.plantuml @@ -0,0 +1,67 @@ +` Generate image using plantuml +` http://plantuml.com/sequence-diagram + +@startuml + +title High-level end-to-end LSAT authentication flow + +participant "Client " as client +participant "Client lnd " as clnd #cccccc +participant "Auth server " as auth +participant "Auth server lnd " as alnd #cccccc +participant "Protected resource " as res #ff6666 + +group First time user + + activate client + client -> auth: GET /protected + activate auth + + auth -> auth: Check token,\nno token found + + auth -> alnd: Generate invoice + activate alnd + + alnd --> auth: Invoice + deactivate alnd + + auth -> auth: Create token \n+ invoice + + auth --> client: 402: Payment Required,\ntoken + invoice + deactivate auth + + client -> clnd: Pay invoice + activate clnd + + clnd -> alnd: Pay invoice + activate alnd + + alnd --> clnd: Preimage + deactivate alnd + + clnd --> client: Preimage + deactivate clnd + + client -> client: Add preimage to \ntoken +end + +group User with a token + + client -> auth: GET /protected,\ntoken + preimage + activate auth + + auth -> auth: Check token,\nvalidate payment + + auth -> res: GET /protected + activate res + + res --> auth: Protected content + deactivate res + + auth --> client: Protected content + deactivate auth + + deactivate client +end + +@enduml \ No newline at end of file diff --git a/blip-0026/e2e-flow.png b/blip-0026/e2e-flow.png new file mode 100644 index 0000000..e495569 Binary files /dev/null and b/blip-0026/e2e-flow.png differ