Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 46 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@
L402 is an open protocol for paying for and authenticating access to APIs and
services over the internet using the Lightning Network. Developed by
[Lightning Labs](https://lightning.engineering/), it brings to life the
long-dormant HTTP `402 Payment Required` status code by combining macaroons
(cryptographic bearer credentials) with Lightning Network micropayments.
long-dormant HTTP `402 Payment Required` status code by combining cryptographic
authentication tokens with Lightning Network micropayments.

## How It Works

1. A client requests a paid resource from a server.
2. The server responds with `402 Payment Required`, including an authentication
macaroon and a Lightning invoice in the `WWW-Authenticate` header.
token and a Lightning invoice in the `WWW-Authenticate` header.
3. The client pays the invoice over Lightning, receiving a payment preimage as
proof of payment.
4. The client re-sends the request with the macaroon and preimage in the
4. The client re-sends the request with the token and preimage in the
`Authorization` header.
5. The server verifies the credential and serves the resource.

The macaroon cryptographically commits to the payment hash of the invoice, so
the server can verify payment using only the macaroon and preimage. No database
lookups or session state required.
The token cryptographically commits to the payment hash of the invoice, so the
server can verify payment using only the token and preimage. No database lookups
or session state required.

```
WWW-Authenticate: L402 macaroon="<base64>", invoice="<bolt11>"
Authorization: L402 <base64(macaroon)>:<hex(preimage)>
WWW-Authenticate: L402 version="0", token="<base64>", invoice="<bolt11>"
Authorization: L402 <base64(token)>:<hex(preimage)>
```

## Why L402?
Expand All @@ -36,12 +36,13 @@ collected.
subscriptions, users pay for exactly what they use. A single API call can cost
fractions of a cent.

**Programmable credentials.** Macaroons support attenuation: a credential
holder can create a weaker version of their credential to share with others,
restricting access to specific services, capabilities, or usage limits.
**Programmable credentials.** When using macaroons as the token format (the
recommended default), credentials support attenuation: a token holder can create
a weaker version of their credential to share with others, restricting access to
specific services, capabilities, or usage limits.

**Stateless verification.** Servers verify credentials using only the macaroon
and preimage, no centralized database needed. This makes L402 a natural fit for
**Stateless verification.** Servers verify credentials using only the token and
preimage, no centralized database needed. This makes L402 a natural fit for
distributed systems and microservice architectures.

## Agents and Agentic Commerce
Expand All @@ -59,6 +60,35 @@ human in the loop. As agents increasingly transact with services (and each
other) using real money, L402 provides the payment+authentication layer to make
that work over open payment rails.

## Token Format

L402 is token-format agnostic: any token that commits to a payment hash works.
[Macaroons](docs/macaroons.md) (HMAC-chain bearer credentials) are the
recommended format because they support delegation and attenuation through
caveats, stateless verification via HMAC chains, and service-level access
control with tier encoding. See the
[Macaroon Minting & Verification](docs/macaroons.md) chapter and the
[Macaroon Technical Specification](macaroon-spec.md) for the full details.

## What's New

This revision of the L402 specification aligns with
[bLIP-0026](https://github.com/lightning/blips/blob/master/blip-0026.md) and
includes the following updates:

- **Token generalization.** The protocol is now token-format agnostic. The
`WWW-Authenticate` header uses `token=` instead of the former `macaroon=`.
Macaroons remain the recommended format.
- **Version system.** A `version="0"` parameter is now included in the
`WWW-Authenticate` challenge header, enabling future protocol evolution.
- **Backwards compatibility.** Explicit rules for accepting both `L402`/`LSAT`
scheme names and `token=`/`macaroon=` parameter names.
- **Security guidance.** Expanded security considerations covering caveat-based
token binding (IP, TLS fingerprint, origin domain).
- **Agent specification.** A new [agent-spec.md](agent-spec.md) provides the
complete protocol in ~560 tokens (~420 words), designed for AI agent context
windows.

## Specification

* [Protocol Specification](protocol-specification.md): HTTP and gRPC protocol details, formal definitions
Expand All @@ -76,9 +106,11 @@ that work over open payment rails.
* [Aperture](https://github.com/lightninglabs/aperture): gRPC/HTTP authentication reverse proxy using L402
* [lsat-js](https://github.com/Tierion/lsat-js): JavaScript utility library for working with L402 credentials
* [boltwall](https://github.com/tierion/boltwall): Node.js middleware-based authentication using L402
* [Fewsats](https://www.fewsats.com/): L402-compatible API marketplace and CLI tools

## External Links

* [Builder's Guide Documentation](https://docs.lightning.engineering/the-lightning-network/l402)
* [Macaroons: Cookies with Contextual Caveats (Google Research)](https://research.google/pubs/pub41892/)
* [HTTP/1.1 RFC, Section 6.5.2: 402 Payment Required](https://tools.ietf.org/html/rfc7231#section-6.5.2)
* [bLIP-0026: L402 Protocol Specification](https://github.com/lightning/blips/blob/master/blip-0026.md)
53 changes: 31 additions & 22 deletions agent-spec.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,55 @@
# L402 Agent Specification

Token-efficient reference for L402 protocol integration.
Token-efficient reference for L402 protocol integration. Version 0.

## Core Concept

L402 = HTTP 402 + Lightning invoice + macaroon. Client pays invoice, gets
preimage, presents `(macaroon, preimage)` to authenticate. Stateless
verification: macaroon commits to payment hash H, server checks
`H == sha256(preimage)`.
L402 = HTTP 402 + Lightning invoice + auth token. Client pays invoice, gets
preimage, presents `(token, preimage)` to authenticate. Stateless verification:
token commits to payment hash H, server checks `H == sha256(preimage)`.

## Headers

**Challenge** (server → client):
```
HTTP/1.1 402 Payment Required
WWW-Authenticate: L402 macaroon="<base64>", invoice="<bolt11>"
WWW-Authenticate: L402 version="0", token="<base64>", invoice="<bolt11>"
```

**Authorization** (client → server):
```
Authorization: L402 <base64(macaroon)>:<hex(preimage)>
Authorization: L402 <base64(token)>:<hex(preimage)>
```

Multiple macaroons: comma-separate base64 values before the colon.
Multiple tokens: comma-separate base64 values before the colon.

## Protocol Flow

```
Client → Server: GET /resource
Server → Client: 402 + WWW-Authenticate: L402 macaroon="M", invoice="P"
Server → Client: 402 + WWW-Authenticate: L402 version="0", token="T", invoice="P"
Client → LN: pay(P) → preimage r
Client → Server: GET /resource + Authorization: L402 M:r
Server: verify H == sha256(r), verify macaroon integrity
Client → Server: GET /resource + Authorization: L402 T:r
Server: verify H == sha256(r), verify token integrity
Server → Client: 200 OK + resource
```

## Macaroon Identifier
## Token Requirements

- MUST commit to payment hash H of invoice P
- MUST be verifiable without backend state (stateless)
- RECOMMENDED format: macaroons (HMAC chain, supports caveats/attenuation)
- MAY use any format satisfying above constraints

## Macaroon Identifier (when using macaroons)

Big-endian encoding:

| Field | Size | Description |
|-------|------|-------------|
| version | 2 bytes | uint16, currently 0 |
| payment_hash | 32 bytes | sha256 hash from invoice |
| token_id | 32 bytes | random, tracks user across macaroon rotations |
| token_id | 32 bytes | random, tracks user across token rotations |

## Caveats (macaroon attenuation)

Expand All @@ -59,30 +65,33 @@ Each additional caveat of same key MUST restrict further (never widen).

Same auth scheme. Differences:
- Server MUST return HTTP 200 (gRPC requirement)
- Challenge encoded in `grpc-status-details-bin` as serialized gRPC Status proto
- Client sends macaroon as `Custom-Metadata` key "macaroon"
- Add trailers: `Grpc-Message: payment required`, `Grpc-Status: 13`
- Client sends token as `Custom-Metadata` key "token"

## Backwards Compatibility

- Accept `LSAT` anywhere `L402` appears
- Accept `macaroon=` in addition to `token=` in headers
- Accept missing `version` parameter (pre-versioning clients)

## Credential Lifecycle

- Reuse until revoked (expiry, usage limit, tier upgrade)
- Revoke by deleting root key
- Upgrade: revoke old macaroon, mint new with expanded capabilities
- Revoke by deleting root key (macaroons) or invalidating token
- Upgrade: revoke old token, mint new with expanded capabilities

## Implementation Checklist

Server:
1. Mint macaroon committing to payment hash
2. Return 402 + WWW-Authenticate with macaroon, invoice
3. On auth request: verify macaroon integrity, check `H == sha256(r)`
1. Mint token committing to payment hash
2. Return 402 + WWW-Authenticate with version, token, invoice
3. On auth request: verify token integrity, check `H == sha256(r)`
4. Accept both `L402` and `LSAT` scheme names
5. Accept both `token=` and `macaroon=` parameter names

Client:
1. Parse WWW-Authenticate, extract macaroon + invoice
1. Parse WWW-Authenticate, extract token + invoice
2. Validate invoice amount is acceptable
3. Pay invoice, obtain preimage
4. Send `Authorization: L402 <macaroon>:<preimage>`
4. Send `Authorization: L402 <token>:<preimage>`
5. Cache credential for reuse
24 changes: 12 additions & 12 deletions docs/authentication-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,19 @@ sequenceDiagram
A->>A: Check credential, none found
A->>AL: Generate invoice
AL-->>A: Invoice P
A->>A: Mint macaroon M (commits to H)
A-->>C: 402 Payment Required + WWW-Authenticate: L402 macaroon="M", invoice="P"
A->>A: Create token T (commits to H)
A-->>C: 402 Payment Required + WWW-Authenticate: L402 version="0", token="M", invoice="P"
C->>CL: Pay invoice P
CL->>AL: Pay invoice (LN payment)
AL-->>CL: Preimage r
CL-->>C: Preimage r
C->>C: Store macaroon M + preimage r
C->>C: Store token T + preimage r
end

rect rgb(240, 255, 240)
Note over C,R: User with credential
C->>A: GET /protected + Authorization: L402 M:r
A->>A: Verify macaroon, check H == sha256(r)
A->>A: Verify token, check H == sha256(r)
A->>R: GET /protected (forwarded)
R-->>A: Protected content
A-->>C: 200 OK + Protected content
Expand All @@ -73,30 +73,30 @@ authentication server.
3. The proxy instructs its backing Lightning node to create an invoice over the
small amount required to acquire a fresh credential.

4. In addition to the invoice, the proxy mints a fresh macaroon tied to the
invoice. The macaroon is cryptographically constructed so that it is only
valid once the invoice has been paid (the macaroon identifier commits to the
4. In addition to the invoice, the proxy creates a fresh authentication token
tied to the invoice. The token is cryptographically constructed so that it
is only valid once the invoice has been paid (the token commits to the
invoice's payment hash).

5. The macaroon and invoice are sent back to the client via the
5. The token and invoice are sent back to the client via the
`WWW-Authenticate` header alongside the HTTP 402 status code:
```
WWW-Authenticate: L402 macaroon="<base64>", invoice="<bolt11>"
WWW-Authenticate: L402 version="0", token="<base64>", invoice="<bolt11>"
```

6. The client extracts the invoice and automatically instructs its connected
Lightning node to pay it.

7. Paying the invoice reveals the cryptographic proof of payment (the
preimage). The client stores the preimage alongside the macaroon.
preimage). The client stores the preimage alongside the token.

8. The combination of the macaroon and preimage yields a fully valid L402
8. The combination of the token and preimage yields a fully valid L402
credential that can be cryptographically verified.

9. The client repeats the original request, attaching the L402 credential via
the `Authorization` header:
```
Authorization: L402 <base64(macaroon)>:<hex(preimage)>
Authorization: L402 <base64(token)>:<hex(preimage)>
```

10. The authentication server intercepts the request, extracts the L402, and
Expand Down
9 changes: 8 additions & 1 deletion docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ specification uses a combination of `HTTP` and 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 L402 protocol is token-format agnostic: any authentication token that can
commit to a payment hash may be used. Macaroons (HMAC-chain bearer credentials)
are the RECOMMENDED token format due to their support for delegation,
attenuation of capabilities, and stateless verification. See the
[Macaroon Minting & Verification](macaroons.md) chapter for full details on the
macaroon-based token format.

The system described above isn't a fantasy. L402 is used _today_ in production
to serve as an authentication+payment solution for services built on the
Lightning Network. The reference implementation is
Expand Down Expand Up @@ -65,7 +72,7 @@ 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
## HTTP + Tokens + 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
Expand Down
5 changes: 5 additions & 0 deletions docs/macaroons.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

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/).

**Note:** The macaroon identifier structure and caveat formats described in
this chapter are RECOMMENDED conventions. Implementations MAY use alternative
token formats provided they satisfy the core L402 protocol requirements
(see [Protocol Specification](../protocol-specification.md), Section 5.3).

## 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.
Expand Down
Loading