``` 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) * [Example Applications and Use Cases](#example-applications-and-use-cases) * [Rationale](#rationale) * [Specification](#specification) * [Authentication Flow](#authentication-flow) * [Reusing Credentials](#reusing-credentials) * [Security Considerations](#security-considerations) * [L402 HTTP/gRPC Protocol Specification](#l402-httpgrpc-protocol-specification) * [HTTP Protocol Flow Specification](#http-protocol-flow-specification) * [Server Flow](#server-flow) * [Client Flow](#client-flow) * [gRPC Protocol Specification](#grpc-protocol-specification) * [Server Flow](#grpc-server-flow) * [Client Flow](#grpc-client-flow) * [Universality](#universality) * [Backwards Compatibility](#backwards-compatibility) * [Appendix](#appendix) * [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) * [Reference Implementation](#reference-implementation) # Abstract L402 is a protocol standard based on the HTTP 402 Payment Required status code designed to support the use case of charging for services and authenticating users in distributed networks. The L402 protocol is a concrete instantiation of a Lightning Network based micro-paywall for HTTP/gRPC APIs on the web. A supporting server signals that a payment is required for an endpoint by sending a special `WWW-Authenticate` header along with a 402 status code. This header encodes an authentication token \(the L402 credential\), and a Lightning Network invoice. In order to traverse the L402-enabled endpoint, the client then pays the Lightning Network invoice, and presents the `(token, preimage)` tuple to the server in their next request via an HTTP `Authorization` header. Critically, the L402 token MUST cryptographically commit to the payment hash of the LN invoice sent by the server proxy. This commitment structure enables the server to easily verify that a client has properly paid for the endpoint in a stateless manner, providing in-band payment authentication. The L402 protocol is token-format agnostic: any authentication token that can commit to a payment hash may be used. Macaroons (HMAC chain based bearer credentials) are the RECOMMENDED token format due to their support for delegation, attenuation of capabilities, and stateless verification. See the [Appendix](#appendix) for a full specification of the macaroon-based token format. The L402 protocol can be implemented as a simple reverse-proxy in front of a traditional HTTP/gRPC based backend. The proxy handles the minting + verification of the L402 credentials, decoupling the authentication layer from the target web service backends. In more advanced deployments, a backend may introspect into the L402 token structure to enforce capability verification, and even dynamically communicate with the proxy to dictate real-time pricing in an automated fashion. The L402 protocol gets its name from the HTTP status code 402: Payment Required. # Copyright This bLIP is licensed under the CC0 license. # Motivation The early creators of the Web created a cut out for a future Internet-native payment system in the form of the HTTP 402 Payment Required status code. This status code was intended to be returned if payment was required in order to be able to fetch/interact with the resources at a given HTTP endpoint. The 402 status code thus presented a way to enable HTTP-native payment metered APIs on the Web. With the rise of Bitcoin, and the Lightning Network, the Internet now has a native digital currency and a low-cost, low-latency, high volume payment system to enable highly scalable payments over open payment infrastructure. An L402 credential can serve both as authentication, as well as a payment mechanism \(one can view it as a ticket\) for paid APIs. By using 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 an L402 credential 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 token which can only be created by the end service provider. The L402 specification uses a combination 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. ## 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! 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 use 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. This diagram outlines the high level authentication flow for the protocol: ```mermaid sequenceDiagram participant L as Lightning Node participant C as Client participant S as Server C->>S: GET HTTP/1.1 Request S->>C: HTTP/1.1 402 Payment Required Note over S: WWW-Authenticate: L402 version="0", token="X", invoice="Y" C->>L: Pay invoice L->>C: Returns pre-image C->>S: GET HTTP/1.1 Request Note over C: Authorization: L402 token:preimage S->>S: Verify L402 authorization S->>C: HTTP/1.1 200 OK ``` HTTP-based protocol flow: 1. A client hits an `HTTP` endpoint to fetch a resource. 2. The server decides that payment is required to access the endpoint. They return a HTTP status code of `402` along with a `WWW-Authenticate` header containing a token and invoice. The token MUST commit to the payment hash of the invoice `H`. 3. The client pays the invoice over the Lightning Network and receives the payment pre-image `r` to the payment hash `H`, `H = sha256(r)` 4. The client re-issues the request with an `Authorization` header that includes the payment preimage `r`, and the token sent by the server. 5. The server cryptographically verifies the authenticity and integrity of the token, then ensures the payment hash committed to in the token `H`, satisfies the relation `H = sha256(r)`. 6. The server returns a 200 OK status code along with the specified resource. If the service supports persistent L402 token re-use, then a client SHOULD store the credential as it can be re-used without repeating the initialization step. As seen below, credentials can be easily revoked by the server, expire, and even contain structured information that encodes the capabilities of a credential. ### Reusing Credentials L402 credentials are 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 exposed services. As an example, the same L402 credential may commit to capabilities enabling a user to access both service `Y` and `X` from the same endpoint. This flexibility is afforded because all services are going to be gated by the same L402 proxy, which verifies all credentials 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. Because L402 tokens support attenuation through caveats, this class of attack can be mitigated by cryptographically binding the token to client-specific details. For example, a server (or the client itself, via self-attenuation) could add caveats that restrict the token's validity to a particular IP address, TLS client certificate fingerprint, origin domain, or other client-identifying predicate. The server then verifies these caveats upon each request, ensuring a stolen token cannot be replayed from a different context. Each binding predicate carries its own tradeoffs: an IP caveat prevents use after a network change, while a TLS client cert fingerprint requires the client to maintain a stable key pair. Deployments should choose binding predicates appropriate to their threat model. ## L402 HTTP/gRPC Protocol Specification ### HTTP Protocol Flow Specification In this section, we specify the protocol for the HTTP portion of the L402 proxy. #### Server Flow 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: 1. The server SHOULD derive an economical price for the endpoint expressed in milli-satoshis \(1/1000th of a satoshi\) and create a [BOLT 11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) invoice `P` requesting that amount from its backing Lightning Node. 2. The server MUST create a new authentication token `T` for the client that will only become valid once the client pays the LN invoice. 1. The token MUST commit to the payment hash `H` of the invoice `P`. This commitment is what provides in-band payment authentication: the server can verify that a client has paid using only the token and the preimage, without any backend lookup or additional state. Without this commitment, the server would need to maintain a large amount of state to validate all past, current, and future credentials. 3. The server MUST 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.** 4. Alongside the 402 status code, the server MUST 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 token needed for the client to form a complete L402. A valid response header MUST take the form of: ``` WWW-Authenticate: L402 version="0", token="T", invoice="P" ``` Where: * `version`: A protocol version string. The current version is `"0"`. Clients MUST ignore unknown key=value parameters in the challenge header, to allow future extensions to the protocol \(e.g., alternative invoice formats\). * `token`: The authentication token, encoded as base64. The token MUST commit to the payment hash `H` of the invoice `P`. * `invoice`: A [BOLT 11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) payment request that the client MUST pay in order to obtain the preimage required to complete the `Authorization` header. An example L402 HTTP response resembles: ```text HTTP/1.1 402 Payment Required Date: Mon, 04 Feb 2014 16:50:53 GMT WWW-Authenticate: L402 version="0", token="AGIAJEemVQUTEyNCR0exk7ek90Cg==", invoice="lnbc1500n1pw5kjhmpp5fu6xhthlt2vucmzkx6c7wtlh2r625r30cyjsfqhu8rsx4xpz5lwqdpa2fjkzep6yptksct5yp5hxgrrv96hx6twvusycn3qv9jx7ur5d9hkugr5dusx6cqzpgxqr23s79ruapxc4j5uskt4htly2salw4drq979d7rcela9wz02elhypmdzmzlnxuknpgfyfm86pntt8vvkvffma5qc9n50h4mvqhngadqy3ngqjcym5a" ``` where `"AGIAJEemVQUTEyNCR0exk7ek90Cg=="` is the token that the client MUST include for each of its authorized requests and `"lnbc1500n1pw5kjhmpp..."` is the BOLT 11 invoice the client must pay to reveal the preimage that must be included for each of its authorized requests. Upon receiving an HTTP request with a valid [RFC-7235](https://datatracker.ietf.org/doc/html/rfc7235) `Authorization` header: 1. The server MUST verify the cryptographic authenticity and integrity of the credential. 1. If a credential is invalid, then the server MUST return a 401 Unauthorized status code. 2. The server MUST parse out the `Authorization` header \(`token:preimage`\) into `T` the base64-encoded token, and `r` the hex-encoded payment preimage. 3. The server MUST verify that the BOLT 11 invoice tied to the token `T` has been paid. 1. If the server committed to the payment hash `H` in the token `T`, then they can simply verify that `H = sha256(r)`. 2. Otherwise, the server should verify that the invoice `P` has been paid in full. 4. If the invoice has not been paid in full, then the server MUST return a 401 Unauthorized header. Otherwise, the server SHOULD process the request itself, or pass it on to the proxied backend. Regarding step 3.1 and 3.2, it's imperative that the server ensure that the invoice has been paid in full before processing the response, or proxying it to a backend. As stated above, by cryptographically committing to the payment hash, the server can implement fast stateless verification of the payment hash+preimage relation. #### Client Flow Upon receiving a valid L402 `WWW-Authenticate` header the client: 1. Should verify that the contained BOLT 11 invoice doesn't request an excessive amount of Bitcoin. 1. If so, then the client SHOULD abandon the HTTP request. 2. After validating the returned BOLT 11 invoice, the client MUST pay the invoice over the LN to receive the payment pre-image `r`. 3. The client then constructs a valid `Authorization` header with the following form: `Authorization: L402 :` 4. The client then re-issues the original HTTP request with the attached L402 `Authorization` header. In other words, to receive authorization, the client: * Pays the invoice from the server, thus revealing the invoice's preimage * Constructs the L402 by concatenating the base64-encoded token\(s\), a single colon \(":"\), and the hex-encoded preimage. 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: `auth-tokens` → [_<base64 encoding>_](https://tools.ietf.org/html/rfc3548#section-3), comma separated if multiple auth tokens are present `preimage` → [_<hex encoding>_](https://tools.ietf.org/html/rfc3548#section-6) `L402 credential` → auth-tokens ":" preimage Specifically, the syntax for "L402 credential" 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. Since the token 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 token 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 token `"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 gRPC variant of the L402 authentication scheme. While gRPC is itself transmitted over HTTP, it uses special trailing headers to delineate protocol-specific information. In addition, the [gRPC specification requires that a status code of 200 is _always_ sent in responses](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#responses). As a result, the protocol flow is modified slightly to always send a 200 OK status code, and instead insert the relevant L402 headers as gRPC trailing headers. #### Server Flow The server flow when receiving a URI that lacks credentials or is invalid is identical to the HTTP protocol flow with the following modifications: 1. The server MUST reply with a challenge using the 200 OK status code. 2. Alongside the normal `WWW-Authenticate` header, the server MUST send the following trailing headers: * `Grpc-Message: payment required` * `Grpc-Status`: 13 # Internal As an example: ```text HTTP/2 200 OK Date: Mon, 04 Feb 2014 16:50:53 GMT Content-Type: application/grpc … Grpc-Message: payment required Grpc-Status: 13 ``` #### Client Flow The gRPC flow for the client is identical to the HTTP flow, with one addition: the client MUST also transmit the final token as `Custom-Metadata`, with a key of "token" and value of the hex-encoded serialized token. All other gRPC headers and trailers are required as normal; more information can be found in the [_gRPC over HTTP2 specification_](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md). # 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. Earlier versions of this specification used `macaroon` as the key name in the `WWW-Authenticate` challenge header \(e.g., `L402 macaroon="X", invoice="Y"`\) and in the gRPC `Custom-Metadata` key. To preserve backwards compatibility with deployed clients and servers: * Servers SHOULD accept `macaroon=` in addition to `token=` when parsing client requests and `WWW-Authenticate` headers from upstream proxies. * Clients SHOULD accept both `token=` and `macaroon=` when parsing `WWW-Authenticate` challenge headers from servers. * Servers SHOULD accept the gRPC `Custom-Metadata` key "macaroon" in addition to "token". The `version` parameter in the `WWW-Authenticate` header was introduced in this revision. Old clients that do not understand the `version` parameter will ignore it per the "unknown parameters MUST be ignored" rule. Servers SHOULD accept requests that omit the `version` parameter. # Appendix ## Macaroon Minting & Verification Macaroons are the RECOMMENDED authentication token format for L402. Macaroons are HMAC chain based bearer credentials that naturally commit to a payment hash as part of their identifier structure, making them ideal for stateless L402 verification. 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. > Note: The macaroon identifier structure and caveat formats described in this > appendix are RECOMMENDED conventions. Implementations MAY use alternative > token formats provided they satisfy the core L402 protocol requirements > \(committing to the payment hash, stateless 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 token, which specifies the allowed capabilities of the credential, and a preimage, which serves as the credential's proof of payment. 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. # Reference Implementation * [Aperture: A gRPC/HTTP authentication reverse proxy using L402s](https://github.com/lightninglabs/aperture) * [lsat-js: 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) * [Fewsats: L402-compatible API marketplace and CLI tools](https://www.fewsats.com/)