├── README.md ├── SUMMARY.md ├── authentication-flow.md ├── introduction.md ├── macaroons.md ├── plantuml ├── e2e-flow.plantuml └── e2e-flow.png └── protocol-specification.md /README.md: -------------------------------------------------------------------------------- 1 | # L402: Lightning HTTP 402 Protocol 2 | 3 | L402 is a standard to support the use case of charging for services and authenticating users in distributed networks. Developed by [Lightning Labs](https://lightning.engineering/), 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 error code _402 Payment Required_ 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. 4 | 5 | This repository outlines the open source design for L402, formerly published under the name LSAT. We welcome contributions to this repository. 6 | 7 | An L402 is created like a [Macaroon](macaroons.md). 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. 8 | 9 | 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. 10 | 11 | A valid L402, 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 can be verified using minimal information and basic cryptography. 12 | 13 | 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. They can be viewed as a global HTTP 402 reverse proxy at the load balancing level for all services. 14 | 15 | Today, L402 is implemented in [Aperture](https://github.com/lightninglabs/aperture) and used for authentication in Lightning Lab’s [Loop](https://github.com/lightninglabs/loop) and [Pool](https://github.com/lightninglabs/pool) services for authentication. 16 | 17 | * [Introduction](introduction.md) 18 | * [Authentication flow](authentication-flow.md) 19 | * [Protocol Specification](protocol-specification.md) 20 | * [Macaroon Minting & Verification](macaroons.md) 21 | 22 | ## Implementations 23 | 24 | * [Aperture: A gRPC/HTTP authentication reverse proxy using L402s](https://github.com/lightninglabs/aperture) 25 | * [A utility library for working with L402s](https://github.com/Tierion/lsat-js) 26 | * [boltwall: Nodejs middleware-based authentication using L402s](https://github.com/tierion/boltwall) 27 | 28 | ## External links / References 29 | 30 | * [Builder's Guide Documentation](https://docs.lightning.engineering/the-lightning-network/l402) 31 | * [L402 Playground](https://lsat-playground.bucko.now.sh/) 32 | * [Macaroons: Cookies with Contextual Caveats](https://research.google/pubs/pub41892/) 33 | * [HTTP/1.1 RFC, Section 6.5.2: 402 Payment Required](https://tools.ietf.org/html/rfc7231#section-6.5.2) 34 | 35 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | 3 | * [L402: Lightning Service Authentication Token](README.md) 4 | * [Introduction](introduction.md) 5 | * [Authentication Flow](authentication-flow.md) 6 | * [Protocol Specification](protocol-specification.md) 7 | * [Macaroon Minting & Verification](macaroons.md) 8 | 9 | -------------------------------------------------------------------------------- /authentication-flow.md: -------------------------------------------------------------------------------- 1 | # Authentication Flow 2 | 3 | This chapter explains the high-level authentication flow from the perspective of a user and their client software. 4 | 5 | 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. 6 | 7 | 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. 8 | 9 | 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. 10 | 11 | ## Detailed authentication flow 12 | 13 | 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. 14 | 15 | 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. 16 | 17 | **First time looping out**: 18 | 19 | 1. A loop user wishes to perform a swap with the loop server. They type the 20 | 21 | command `loop out ` and hit return. 22 | 23 | 2. The `loopd` client program contacts the loop server to initiate the swap. 24 | 25 | 3. The call from the client must always go through the authentication server 26 | 27 | reverse proxy, which in this example is `aperture`. The authentication proxy 28 | 29 | notices that the client didn't send an L402 and therefore cannot be granted 30 | 31 | access to the loop server. 32 | 33 | 4. `aperture` instructs its own `lnd` instance to create an invoice over a small 34 | 35 | amount that is required to acquire a fresh credential. 36 | 37 | 5. In addition to the invoice, `aperture` also creates a fresh access credential that is 38 | 39 | tied to the invoice. The credential is cryptographically constructed in a way that 40 | 41 | it is only valid once the invoice has been paid. 42 | 43 | 6. The credential and the invoice are sent back to the client in the previously 44 | 45 | unused HTTP header `402 Payment Required`. 46 | 47 | 7. The `loopd` understands this returned error code, extracts the invoice from 48 | 49 | it and automatically instructs its connected `lnd` instance to pay the 50 | 51 | invoice. 52 | 53 | 8. Paying the invoice results in the `loopd` client now possessing the 54 | 55 | cryptographic proof of payment \(the pre-image\). This proof is stored in the 56 | 57 | client's local storage, together with the access credential. 58 | 59 | 9. The combination of the access credential and the pre-image yields a fully valid 60 | 61 | L402 that can be cryptographically verified. 62 | 63 | 10. The client now repeats the original request to the loop server, now 64 | 65 | attaching the L402 to the request. 66 | 67 | 11. The authentication server intercepts the request, extracts the L402 and 68 | 69 | validates it. Because the L402 is valid, the request is forwarded to the 70 | 71 | actual loop server that then initiates the swap. 72 | 73 | 12. The answer of the swap server is returned to the client and the swap is 74 | 75 | now initiated. 76 | 77 | 13. The whole process is fully transparent to the user. The only thing they 78 | 79 | might notice is a short delay of a few seconds on the first ever loop. Each 80 | 81 | successive loop will use the same credential and will not be delayed at all. 82 | 83 | ![e2e flow sequence diagram](plantuml/e2e-flow.png) 84 | 85 | **All further loops**: 86 | 87 | 1. For every new request to the server, the client now automatically attaches 88 | 89 | the credential that is stored locally. 90 | 91 | 2. As long as the credential has not expired, the steps 9-13 above will be followed. 92 | 93 | If/when the credential expires, the server will start over at step 4 and instruct 94 | 95 | the client to obtain a fresh credential. 96 | 97 | -------------------------------------------------------------------------------- /introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | 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. 4 | 5 | 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. 6 | 7 | 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. 8 | 9 | ## The Forgotten HTTP Error Code 10 | 11 | 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. 12 | 13 | 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. 14 | 15 | ## Authentication and API Payments in a Lightning-Native Web 16 | 17 | 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? 18 | 19 | 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. 20 | 21 | 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"? 22 | 23 | ## HTTP + Macaroons + Lightning = L402 24 | 25 | 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. 26 | 27 | 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)`\). 28 | 29 | 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. 30 | 31 | ## Example Applications and Use Cases 32 | 33 | 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. 34 | 35 | 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! 36 | 37 | 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. 38 | 39 | ## Conclusion 40 | 41 | In this section we've provided an overview of the lineage, motivation, workflow, potential and uses cases for the L402 standard. In the later sections, we'll dive a bit deeper, fully specifying the L402 protocol end to end. 42 | 43 | -------------------------------------------------------------------------------- /macaroons.md: -------------------------------------------------------------------------------- 1 | # Macaroon Minting & Verification 2 | 3 | ## Overview 4 | 5 | In this chapter, 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/). 6 | 7 | ## Minting Macaroons 8 | 9 | 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. 10 | 11 | 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. 12 | 13 | ### Macaroon Identifier 14 | 15 | 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: 16 | 17 | > Note: All data specified here are encoded in big-endian unless otherwise stated. 18 | 19 | * **Version** - A version allows for an iterative Macaroon design. It must be encoded in 2 bytes unsigned integer. 20 | * **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. 21 | * **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 mMcaroon’s identifier because the latter can be revoked, e.g., in the case of a service tier upgrade. 22 | 23 | ## Attenuation Through Caveats 24 | 25 | 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. 26 | 27 | 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. 28 | 29 | ### Target Services 30 | 31 | 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. 32 | 33 | 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. 34 | 35 | ### Service Capabilities 36 | 37 | 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. 38 | 39 | 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. 40 | 41 | ### Service Constraints 42 | 43 | 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. 44 | 45 | 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. 46 | 47 | 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: 48 | 49 | ```text 50 | identifier: 51 | version = 0 52 | user_id = fed74b3ef24820f440601eff5bfb42bef4d615c4948cec8aca3cb15bd23f1013 53 | payment_hash = 163102a9c88fa4ec9ac9937b6f070bc3e27249a81ad7a05f398ac5d7d16f7bea 54 | caveats: 55 | services = lightning_loop:0 56 | lightning_loop_capabilities = loop_out,loop_in 57 | loop_out_monthly_volume_sats = 200000000 58 | ``` 59 | 60 | 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: 61 | 62 | ```text 63 | lightning_loop_capabilities = loop_in 64 | loop_in_monthly_volume_sats = 100000000 65 | ``` 66 | 67 | ## Macaroon Verification 68 | 69 | 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. 70 | 71 | 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. 72 | 73 | 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. 74 | 75 | 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. 76 | 77 | ## Macaroon Revocation 78 | 79 | 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. 80 | 81 | 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. 82 | 83 | -------------------------------------------------------------------------------- /plantuml/e2e-flow.plantuml: -------------------------------------------------------------------------------- 1 | ` Generate image using plantuml 2 | ` http://plantuml.com/sequence-diagram 3 | 4 | @startuml 5 | 6 | title High-level end-to-end LSAT authentication flow 7 | 8 | participant "Client " as client 9 | participant "Client lnd " as clnd #cccccc 10 | participant "Auth server " as auth 11 | participant "Auth server lnd " as alnd #cccccc 12 | participant "Protected resource " as res #ff6666 13 | 14 | group First time user 15 | 16 | activate client 17 | client -> auth: GET /protected 18 | activate auth 19 | 20 | auth -> auth: Check token,\nno token found 21 | 22 | auth -> alnd: Generate invoice 23 | activate alnd 24 | 25 | alnd --> auth: Invoice 26 | deactivate alnd 27 | 28 | auth -> auth: Create token \n+ invoice 29 | 30 | auth --> client: 402: Payment Required,\ntoken + invoice 31 | deactivate auth 32 | 33 | client -> clnd: Pay invoice 34 | activate clnd 35 | 36 | clnd -> alnd: Pay invoice 37 | activate alnd 38 | 39 | alnd --> clnd: Preimage 40 | deactivate alnd 41 | 42 | clnd --> client: Preimage 43 | deactivate clnd 44 | 45 | client -> client: Add preimage to \ntoken 46 | end 47 | 48 | group User with a token 49 | 50 | client -> auth: GET /protected,\ntoken + preimage 51 | activate auth 52 | 53 | auth -> auth: Check token,\nvalidate payment 54 | 55 | auth -> res: GET /protected 56 | activate res 57 | 58 | res --> auth: Protected content 59 | deactivate res 60 | 61 | auth --> client: Protected content 62 | deactivate auth 63 | 64 | deactivate client 65 | end 66 | 67 | @enduml -------------------------------------------------------------------------------- /plantuml/e2e-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lightninglabs/L402/fda63dd8f39b997023d0e02638f8dfae34f7a456/plantuml/e2e-flow.png -------------------------------------------------------------------------------- /protocol-specification.md: -------------------------------------------------------------------------------- 1 | # Protocol Specification 2 | 3 | ## Introduction 4 | 5 | In this chapter, we outline the specification for the abstract L402 HTTP and gRPC protocols. This is intended to be along the lines of the document we would submit if we were submitting the L402 HTTP/gRPC protocol to a standards committee. For more details on the higher-level purpose and motivations behind L402, please [see this chapter](introduction.md). 6 | 7 | ## Specification 8 | 9 | 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. 10 | 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. 11 | 12 | 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. 13 | 14 | The L402 authentication scheme utilizes the Authentication Framework specified in [_RFC 7235_](https://tools.ietf.org/html/rfc7235) as follows. 15 | 16 | In challenges: the scheme name is "L402". Note that the scheme name is case-insensitive. For credentials, the syntax is: 17 | 18 | `macaroons` → [_<base64 encoding>_](https://tools.ietf.org/html/rfc3548#section-3), comma separated if multiple Macaroons are present 19 | `preimage` → [_<hex encoding>_](https://tools.ietf.org/html/rfc3548#section-6) 20 | `token` → macaroons ":" preimage 21 | 22 | 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. 23 | 24 | ### Reusing Credentials 25 | 26 | 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\). 27 | 28 | 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. 29 | 30 | ### Security Considerations 31 | 32 | 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. 33 | 34 | 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. 35 | 36 | ## HTTP Specification 37 | 38 | In this section, we specify the protocol for the HTTP portion of the L402 proxy. 39 | 40 | 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.** 41 | 42 | 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. 43 | 44 | For instance: 45 | 46 | ```text 47 | HTTP/1.1 402 Payment Required 48 | 49 | Date: Mon, 04 Feb 2014 16:50:53 GMT 50 | 51 | WWW-Authenticate: L402 macaroon="AGIAJEemVQUTEyNCR0exk7ek90Cg==", invoice="lnbc1500n1pw5kjhmpp5fu6xhthlt2vucmzkx6c7wtlh2r625r30cyjsfqhu8rsx4xpz5lwqdpa2fjkzep6yptksct5yp5hxgrrv96hx6twvusycn3qv9jx7ur5d9hkugr5dusx6cqzpgxqr23s79ruapxc4j5uskt4htly2salw4drq979d7rcela9wz02elhypmdzmzlnxuknpgfyfm86pntt8vvkvffma5qc9n50h4mvqhngadqy3ngqjcym5a" 52 | ``` 53 | 54 | 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. 55 | 56 | In other words, to receive authorization, the client: 57 | 58 | 1. Pays the invoice from the server, thus revealing the invoice’s preimage 59 | 2. Constructs the L402 by concatenating the base64-encoded Macaroon\(s\), a single 60 | 61 | colon \(":"\), and the hex-encoded preimage. 62 | 63 | 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. 64 | 65 | 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: 66 | 67 | ```text 68 | Authorization: L402 AGIAJEemVQUTEyNCR0exk7ek90Cg==:1234abcd1234abcd1234abcd 69 | ``` 70 | 71 | ## gRPC Protocol Specification 72 | 73 | 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. 74 | 75 | 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. 76 | 77 | 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. 78 | 79 | 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: 80 | 81 | ```javascript 82 | { 83 | code: 402, 84 | message: "missing L402", 85 | details: { 86 | type_url: "type.googleapis.com/google.rpc.QuotaFailure", 87 | value: { 88 | macaroon: "", 89 | invoice: "" 90 | } 91 | } 92 | } 93 | ``` 94 | 95 | Note that deserialization is language-dependent. In Go, it looks something like this: 96 | 97 | ```go 98 | _, err := client.AccessBackendService(ctx, &pb.BackendServiceRequest{}) 99 | If err != nil { 100 | st, _ := status.FromError(err) 101 | message := st.Message() // get message 102 | code := st.Code() // get code 103 | for _, detail := range st.Details() { 104 | switch t := detail.(type) { 105 | case *errdetails.QuotaFailure: 106 | for _, violation := range t.GetViolations() { 107 | // parse macaroon from "macaroon:<mac>" format 108 | // parse invoice from "invoice:<inv>" format 109 | … 110 | ``` 111 | 112 | Serialization is similarly language-dependent. 113 | 114 | 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. 115 | 116 | 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`. 117 | 118 | For instance: 119 | 120 | ```text 121 | HTTP/2 200 OK 122 | Date: Mon, 04 Feb 2014 16:50:53 GMT 123 | Content-Type: application/grpc 124 | … 125 | Grpc-Message: missing L402 126 | Grpc-Status: 402 127 | Grpc-Status-Details-Bin: CJIDEgxtaXNzaW5nIExTQVQaeQ… 128 | ``` 129 | 130 | Where `"CJIDEgxtaXNzaW5nIExTQVQaeQ…"` is the serialized gRPC status proto. 131 | 132 | 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. 133 | 134 | 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: 135 | 136 | ```text 137 | Authorization: L402 AGIAJEemVQUTEyNCR0exk7ek90Cg==:1234abcd1234abcd1234abcd 138 | ``` 139 | 140 | 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). 141 | 142 | --------------------------------------------------------------------------------