This document specifies the L402 authentication scheme for HTTP and gRPC. L402 combines the HTTP 402 Payment Required status code with Lightning Network invoice payments to create a challenge-response protocol for paid API access. A server issues a challenge containing an authentication credential and a Lightning invoice; the client pays the invoice to obtain a preimage, then presents the credential and preimage together as proof of payment.
The credential is a macaroon (an
HMAC-chain bearer token) that cryptographically commits to the invoice's
payment hash. This binding enables stateless verification: the server checks
H == sha256(preimage) against the hash embedded in the macaroon, with no
database lookup required. See Macaroon Minting & Verification
for a full treatment of the macaroon format.
For higher-level motivation and use cases, see the Introduction.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 (RFC 2119, RFC 8174) when, and only when, they appear in all capitals, as shown here.
L402 Credential. A <macaroon>:<preimage> pair transmitted in the HTTP
Authorization header. The macaroon is base64-encoded; the preimage is
hex-encoded. This is the artifact a client presents to prove payment.
Macaroon. An HMAC-chain bearer credential minted by the server. The macaroon's identifier commits to the payment hash of a Lightning invoice. Macaroons support caveats (restrictions) and attenuation (delegation with reduced authority). See the Macaroon Technical Specification for construction details.
Preimage. The 32-byte value r such that sha256(r) equals the payment
hash of the Lightning invoice. Possession of the preimage proves the invoice
was paid.
Payment Hash. The SHA-256 hash H of the preimage, embedded in both the
Lightning invoice and the macaroon identifier. The binding H == sha256(r) is
the core verification primitive.
Challenge. The WWW-Authenticate: L402 ... header returned by the server
alongside HTTP 402, containing a macaroon and a Lightning invoice.
Caveat. A restriction appended to a macaroon's HMAC chain. Caveats can encode service access, capabilities, expiration, volume limits, and other constraints. Each successive caveat can only narrow the macaroon's authority, never widen it.
sequenceDiagram
participant C as Client
participant S as Server
participant LN as Lightning Network
C->>S: GET /resource
S-->>C: 402 Payment Required<br/>WWW-Authenticate: L402 macaroon="M", invoice="P"
C->>LN: pay(P)
LN-->>C: preimage r
C->>S: GET /resource<br/>Authorization: L402 M:r
S->>S: verify macaroon, check H == sha256(r)
S-->>C: 200 OK + resource
| Condition | Status | Response |
|---|---|---|
| Resource requires payment, no credential provided | 402 | WWW-Authenticate challenge with macaroon + invoice |
| Credential present but macaroon invalid or tampered | 401 | Unauthorized |
| Credential present but preimage does not match payment hash | 401 | Unauthorized |
| Credential valid, access granted | 200 | Requested resource |
The 402 status code is used exclusively for the initial payment challenge. Once a client presents a credential (valid or not), the server MUST respond with 401 if verification fails, not 402. This distinction lets clients differentiate "you need to pay" from "your credential is broken."
The L402 scheme is registered under the HTTP Authentication Framework specified in RFC 7235. The scheme name is "L402" (case-insensitive).
When a server requires payment for a resource, it MUST respond with HTTP 402
and include a WWW-Authenticate header of the form:
WWW-Authenticate: L402 macaroon="<base64>", invoice="<bolt11>"
Parameters:
-
macaroon(REQUIRED): The authentication macaroon, base64-encoded (RFC 4648). The macaroon MUST commit to the payment hashHof the invoicePin its identifier (see Macaroon Technical Specification, Section "Identifier Structure"). -
invoice(REQUIRED): A BOLT 11 payment request. The client MUST pay this invoice to obtain the preimage required to complete theAuthorizationheader.
Example:
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 the client must
include in each authorized request, and "lnbc1500n1pw5kjhmpp..." is the
BOLT 11 invoice the client must pay to reveal the preimage.
The L402 credential is transmitted in the Authorization header using the
following syntax:
Authorization: L402 <base64(macaroon)>:<hex(preimage)>
Where:
- The macaroon is base64-encoded per RFC 4648. Multiple macaroons are base64-encoded individually and comma-separated before the colon.
- The preimage is hex-encoded per RFC 3548, Section 6.
This syntax is comparable to the "token68" syntax used for HTTP Basic auth.
Example:
Authorization: L402 AGIAJEemVQUTEyNCR0exk7ek90Cg==:1234abcd1234abcd1234abcd
Since the macaroon and preimage are both binary data encoded in ASCII, there is no issue with control characters or colons (see "CTL" in Appendix B.1 of RFC 5234). If a client provides a macaroon or preimage containing control characters, the server MUST treat it as an invalid L402 and respond with 401.
l402-challenge = "L402" 1*SP l402-params
l402-params = macaroon-param "," SP invoice-param
macaroon-param = "macaroon" "=" quoted-string
invoice-param = "invoice" "=" quoted-string
l402-credential = "L402" 1*SP macaroons ":" preimage
macaroons = base64 *("," base64)
preimage = 1*HEXDIG
base64 = 1*( ALPHA / DIGIT / "+" / "/" / "=" )
Upon receipt of a request for a resource that requires payment and lacks a valid L402 credential:
-
The server SHOULD derive a price for the resource expressed in millisatoshis (1/1000th of a satoshi) and create a BOLT 11 invoice
Prequesting that amount from its backing Lightning node. -
The server MUST mint a new macaroon
Mfor the client. The macaroon MUST commit to the payment hashHof the invoicePin its identifier. This commitment enables in-band payment verification: the server can confirm a client has paid using only the macaroon and preimage, with no additional state or backend lookup. -
The server MUST reply with HTTP 402 (Payment Required). Officially, the HTTP specification marks 402 as "reserved for future use", but this document assumes the future has arrived.
-
The server MUST include a
WWW-Authenticateheader per Section 5.1 containing the macaroon and invoice.
Upon receiving a request with an Authorization: L402 header:
-
The server MUST verify the cryptographic integrity of the macaroon (HMAC chain verification against the root key). If the macaroon is invalid, the server MUST return 401 Unauthorized.
-
The server MUST parse the
Authorizationheader into the base64-encoded macaroonMand the hex-encoded preimager. -
The server MUST verify that the invoice tied to the macaroon has been paid:
- If the server committed to the payment hash
Hin the macaroon, it can verify thatH == sha256(r). This is the RECOMMENDED approach as it enables stateless verification. - Otherwise, the server SHOULD verify that the invoice
Phas been paid in full via its Lightning node.
- If the server committed to the payment hash
-
If verification fails, the server MUST return 401 Unauthorized. Otherwise, the server SHOULD process the request or forward it to the proxied backend.
It is imperative that the server ensure payment before processing the request or forwarding it to a backend. By cryptographically committing to the payment hash in the macaroon, the server can perform fast, stateless verification of the payment hash + preimage relation.
Upon receiving a WWW-Authenticate: L402 challenge:
-
The client SHOULD verify that the BOLT 11 invoice does not request an excessive amount of Bitcoin. If the amount exceeds a configured threshold, the client SHOULD abandon the request.
-
After validating the invoice, the client MUST pay the invoice over the Lightning Network to obtain the payment preimage
r. -
The client MUST construct an
Authorizationheader per Section 5.2:Authorization: L402 <base64(macaroon)>:<hex(preimage)> -
The client MUST re-issue the original HTTP request with the
Authorizationheader attached.
gRPC is transmitted over HTTP/2 but uses special trailing headers for protocol-specific information. The gRPC specification requires a status code of 200 in all responses. As a result, the L402 gRPC flow is modified to always return 200 OK at the HTTP level and instead convey the payment challenge via gRPC trailing headers.
The server flow is identical to the HTTP flow (Section 6.1) with the following modifications:
-
The server MUST reply with HTTP 200 OK (not 402).
-
The server MUST encode the L402 challenge as a serialized gRPC Status proto in the
grpc-status-details-bintrailing header. The deserialized proto contains the macaroon and invoice:{ code: 402, message: "missing L402", details: { type_url: "type.googleapis.com/google.rpc.QuotaFailure", value: { macaroon: "<macaroon>", invoice: "<invoice>" } } }
-
The server MUST include the following trailing headers:
Grpc-Message: missing L402Grpc-Status: 402
Example:
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...
The L402 proxy determines whether a request is gRPC by checking whether the
Content-Type header begins with application/grpc. The proxy MUST be HTTP/2
compatible, since gRPC clients expect an HTTP/2-speaking server.
The gRPC client flow is identical to the HTTP flow (Section 6.2). Once the client has deserialized the proto and extracted the macaroon and invoice, it pays the invoice and constructs the L402 credential identically to the HTTP case (concatenating base64-encoded macaroon, colon, hex-encoded preimage).
Other gRPC headers and trailers are required as normal; see the gRPC over HTTP2 specification for details.
L402 credentials are intended for reuse. A client SHOULD cache and reuse its credential until the server rejects it with a new 402 challenge. An L402 can be scoped to a single backend service or apply across all services behind the same L402 proxy, since the proxy verifies all macaroons for all backends.
Possible revocation conditions include:
- Expiry date encoded as a caveat
- Exceeded usage count
- Volume of usage in a time period that necessitates a tier upgrade
- Explicit server-side revocation (by deleting the root key)
When a credential is revoked, the server issues a fresh 402 challenge and the client repeats the payment flow.
L402 credentials are bearer tokens. The macaroon and preimage are transmitted as cleartext in HTTP headers and MUST be protected by TLS. Implementations MUST use TLS 1.2 (RFC 5246) or later; TLS 1.3 (RFC 8446) is RECOMMENDED.
Servers MUST NOT issue L402 challenges over unencrypted HTTP. Clients MUST NOT send L402 credentials over unencrypted HTTP.
If a client's L402 is intercepted by an attacker (e.g., via a compromised TLS termination point), the attacker can reuse the credential. The L402 proxy would not be able to distinguish this usage as illicit, since the credential is a bearer token.
L402 is vulnerable to spoofing if a client connects to a malicious server (e.g., by mistyping a URL). The malicious server could store the client's L402 and reuse it.
Because macaroons support attenuation through caveats, this class of attack can be mitigated by binding the credential to client-specific details. A server (or the client itself, via self-attenuation) could add caveats restricting validity to a particular IP address, TLS client certificate fingerprint, origin domain, or other client-identifying predicate. The server then verifies these caveats on each request, ensuring a stolen credential cannot be replayed from a different context.
Each binding predicate carries its own tradeoffs: an IP caveat prevents use after a network change; a TLS client cert fingerprint requires the client to maintain a stable key pair. Deployments SHOULD choose binding predicates appropriate to their threat model.
The macaroon itself does not inherently prevent replay. Replay protection comes from the caveat and revocation mechanisms: expiry caveats, usage-count tracking, and root key deletion all limit the window in which a stolen credential is useful.
Clients MUST verify that the invoice amount is reasonable for the requested resource before paying. Malicious servers could request arbitrarily large payments. Client implementations SHOULD enforce a configurable maximum payment threshold.
The L402 protocol was formerly known as LSAT. To preserve backwards compatibility with deployed clients and servers:
- Servers SHOULD send both
LSATandL402scheme names inWWW-Authenticatechallenge headers. TheLSATheader SHOULD appear first for compatibility with older client implementations. - Clients and servers MUST accept both
LSATandL402inAuthorizationheaders.
- RFC 2119: Key words for use in RFCs
- RFC 4648: Base Encodings
- RFC 5234: ABNF
- RFC 5246: TLS 1.2
- RFC 7235: HTTP Authentication
- RFC 7231: HTTP Semantics (402)
- RFC 8174: RFC 2119 Clarification
- RFC 8446: TLS 1.3
- BOLT 11: Invoice Protocol
- Macaroons: Cookies with Contextual Caveats (Google Research)
- gRPC over HTTP2