Skip to content

gofeuer/l402

Repository files navigation

L402 Core - HTTP 402 Library for Lightning Payments

Release Version GitHub go.mod Go version macaroon.v2 GitHub Actions Workflow Status Go Report Card Lightning Network

Inspired by the HTTP 402 Payment Required status code, L402 introduces a novel approach to secure access and dynamic pricing. Whether you’re building a subscription-based platform, a content delivery service, or an API, L402 empowers you to seamlessly integrate payments using the Lightning Network.

L402 Core is a library that bridges the gap between web services, authentication, and payments.

L402 Proxy Middleware

A middleware to secure your endpoints.

import "github.com/gofeuer/l402"

func main() {
	minter := YourMacaroonMinter{}      // Your l402.MacaroonMinter implementation.
	authorizer := YourAccessAuthority{} // Your l402.AccessAuthority implementation.

	// Create a L402 proxy by passing a l402.MacaroonMinter and a l402.AccessAuthority.
	proxy := l402.Proxy(minter, authorizer)

	// Use `proxy` as a middleware to endpoints that require payment.
	http.Handle("GET /", proxy(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "premium content")
	})))

	http.ListenAndServe(":8080", http.DefaultServeMux)
}

Features

  • HTTP 402 Integration: L402 leverages the HTTP 402 status code to signal that payment is required to access a resource. Say goodbye to traditional paywalls; L402 brings a more elegant solution.

  • Macaroons for Authorization: We’ve baked in macaroons! These delightful authorization tokens allow you to package attributes and capabilities alongside your payment request. Dynamic pricing? Check. Automated tier upgrades? Absolutely.

  • Lightning Network Magic: L402 dances with the Lightning Network. Users pay for services over Lightning, and in return, they receive preimages-cryptographic keys that unlock access. It’s like a secret handshake, but with satoshis.

Components

To use L402 Core you need to provide the L402 middleware a couple of components:

An implementation of l402.MacaroonMinter

The minter is used by the authentication handler to provide the user a new set of macaroons and an invoice.

type YourMacaroonMinter struct {
	// connection to a lighting node
	// key storage for macaroon rootKeys
}

func (m YourMacaroonMinter) MintWithChallenge(r *http.Request) (string, l402.Challenge, error) {
	var paymentHash [32]byte
	var id [32]byte

	// A l402.Identifier is encoded and used as the macaroon's ID.
	macaroonID, _ := l402.MarchalIdentifier(l402.Identifier{
		PaymentHash: paymentHash, // Hash of the secret revealed by paying the invoice.
		ID:          id,          // An unique ID assigned to this macaroon.
	})

	rootKey := []byte("{secret_key}") // A secret key that is used to sign and verify your macaroons.

	// Create a macaroon that when paid gives access to the resource requested by: (r *http.Request)
	mac, _ := macaroon.New(rootKey, macaroonID, "", macaroon.LatestVersion)

	macaroonsBase64, _ := l402.MarshalMacaroons(mac) // Accepts multiple macaroons.

	// Provide an invoice from your Lighting node that reveals the secret matching paymentHash.
	challenge := l402.Invoice("lnbc20m1pvjluezpp5q...")

	return macaroonsBase64, challenge, nil
}

An implementation of l402.AccessAuthority

The L402 middleware uses the access authority to determine if a request should be proxied.

type YourAccessAuthority struct {
	// key storage for macaroon rootKeys
}

func (m YourAccessAuthority) ApproveAccess(r *http.Request, macaroons macaroon.Slice, preimage Hash) l402.Rejection {
	for _, macaroon := range macaroons {
		identifier, err := UnmarshalIdentifier(macaroon.Id())
		// Verify if `identifier.PaymentHash` is equal to `preimage`
		// Verify if macaroon is signed by the correct rootKey.
	}

	// Here you should determine if the received macaroons give access to the resource requested by: (r *http.Request)

	// Return nil if the request is approved.
	return errors.New("{rejection reason}")
}

Contributing

Pull requests are welcome! If you have ideas for enhancing L402 Core, feel free to fork the repo and submit your changes.

L402 | Because paying for content should be as smooth as a Lightning bolt. ⚡️🌐