L402: The Missing Piece in the Internet’s Payment Infrastructure
L402: The Missing Piece in the Internet’s Payment Infrastructure
L402 is an open protocol that implements internet-native paywalls by building upon the HTTP 402 Payment Required status code and the Lightning Network.
New Monetization Models
Unlocks new revenue streams by enabling micropayments, pay-per-use and granular access control models.
Open and Extensible
L402’s open protocol encourages innovation and wide adoption across industries, fostering a thriving ecosystem of applications and services.
Language agnostic
L402’s design is universally compatible, ensuring seamless integration across various programming environments and platforms.
Native Digital Payments
Integrates with the Lightning Network for instant, low-cost transactions, perfect for API monetization and digital services.
Granular Access Control
Leveraging macaroons, L402 enables fine-grained access control and secure token management for enhanced security and flexibility.
AI-Friendly Protocol
Built on HTTP, the Lightning Network, and Macaroons, L402 provides a machine-friendly scheme perfect for AI applications and automated systems.
L402 Protocol Flow
sequenceDiagram
participant Client
participant Server
Client->>Server: Request access to HTTP resource
Server–>Server: Check client credentials (invalid)
Server–>Server: Generate challenge (macaroon + invoice)
Server–>>Client: Return HTTP 402 status code & challenge
Client->>Client: Complete challenge & obtain preimage
Client->>Server: Request access L402 Authentication header (macaroon + preimage)
Server->>Server: Verify credentials and proof of completion for the linked challenge
Server–>>Client: Serve the requested resource
Server: Challenge Details
Before processing a request to a protected endpoint, the server issues an L402 challenge by returning a 402 Payment Required HTTP response with the challenge details encoded in a response header.
The challenge includes a macaroon (a token granting specific permissions) and a Lightning Network invoice.
macaroon = "MDAzNmxvY2F0aW9uIGh0dHBzOi8vbHNhdC1wbGF5Z3Jv..." invoice = "lnbc12340n1pny96vwpp5hc4l9wl8ze9jajratkzuxa5..." challenge = "L402 macaroon="{macaroon}" invoice="{invoice}" # The challenge is returned in the response headers response.headers['WWW-Authenticate'] = challenge
Client: Authentication Header
Upon receiving an HTTP 402 Payment Required status, the client extracts the macaroon and Lightning invoice from the challenge.
The client then pays the Lightning invoice and obtains the preimage. Using the macaroon and preimage, the client constructs an authenticated request to the server, which will now be processed since the client has completed the required payment and authentication steps.
# Client prepares the authentication header with the # macaroon and preimage challenge = response.headers['WWW-Authenticate'] macaroon, invoice = parse_challenge(challenge) # Pay the lightning invoice to receive the preimage preimage = pay_invoice(invoice) auth_header = f"L402 {macaroon}:{preimage}" # Client sends a request with the authentication header headers = {'Authorization': f"L402 {macaroon}:{preimage}"} requests.get(url, headers=headers)
Macaroons
Macaroons are a crucial component of the L402 protocol, providing a secure and flexible way to manage client permissions.
They are bearer tokens that contain caveats, which specify the constraints and limitations of the token. In the context of L402, macaroons are used to grant access to specific resources or services based on the client’s payment.
The server generates a macaroon with the appropriate caveats, such as an expiration time or scope limitations, and includes it in the challenge header.
# URL where the credentials can be used location = "fewsats.com" version = 0 payment_hash = "35cf3da4dfdefa01a3859659d447eb2eeb070c9c6610f4..." token_id = "7133548b39c094b83120052b10685d7cc5..." # The identifier needs to be encoded as bytes identifier = encode_id(version, payment_hash, token_id) # The caveats can be used to add constraints to the macaroon caveats = [ "expires_at=2024-06-14T01:38:46Z" ] macaroon = create_macaroon(identifier, location, caveats) print(macaroon.encode()) # AgELZmV3c2F0cy5jb20CQgAANc89pN/e+gG... print(macaroon.json()) # { # "ID": "000035cf3da4dfdefa01a385965...", # "version": 0, # "payment_hash": "35cf3da4dfdefa01a385965...", # "token_id": "7133548b39c094b83120052b106...", # "location": "fewsats.com", # "caveats": [ # "expires_at=2024-06-14T01:38:46Z" # ] # }