
Product
Introducing Repository Access Permissions and Custom Roles
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.
@powforge/l402-verify
Advanced tools
Standalone L402 (Lightning HTTP 402) payment verifier. Zero runtime dependencies. Parses Authorization: L402 <macaroon>: headers, verifies the HMAC-signed macaroon, checks sha256(preimage) === payment_hash, and confirms invoice settlement via LN
Standalone L402 (Lightning HTTP 402) payment verifier. Zero runtime dependencies.
The verification half of @powforge/mcp-l402-gate, extracted as a small, citable reference for the x402 / L402 ecosystem. Use it when you want to accept L402 payments without pulling in the full MCP gate + identity-score stack.
parseL402Header(header) — parse Authorization: L402 <macaroon>:<preimage>verifyMacaroon(macaroon, opts) — recompute the HMAC-SHA256 signature, check expiry, scope, optional replaypreimageMatchesHash(preimage, paymentHash) — constant-time sha256(preimage) === payment_hashcheckInvoicePaid(paymentHash, opts) — single LNBits GET to see if the invoice is settledverifyL402(authHeader, opts) — compose all four into one async call@powforge/mcp-l402-gate)@powforge/identity)usedSet — in-memory Set, Redis, SQLite, whatever you like)npm install @powforge/l402-verify
Requires Node 18+ (for globalThis.fetch).
const { verifyL402 } = require('@powforge/l402-verify');
const result = await verifyL402(req.headers.authorization, {
secret: process.env.L402_SECRET,
expectedScope: 'mcp-l402-gate:call',
lnbitsUrl: process.env.LNBITS_URL,
lnbitsApiKey: process.env.LNBITS_INVOICE_KEY,
usedSet: globalReplaySet, // optional: Set<string> of redeemed preimages
});
if (!result.valid) {
return res.status(401).json({ error: result.reason });
}
// result = { valid: true, paymentHash, scope, caveats, expiresAt, preimage }
const result = await verifyL402(req.headers.authorization, {
secret: process.env.L402_SECRET,
expectedScope: 'pay-per-call',
checkPaidFn: async (paymentHash) => {
// Ask your own Lightning node / wallet
const inv = await lnd.lookupInvoice({ r_hash_str: paymentHash });
return inv.state === 'SETTLED';
},
});
const { parseL402Header, verifyMacaroon, preimageMatchesHash, checkInvoicePaid } = require('@powforge/l402-verify');
const parsed = parseL402Header(req.headers.authorization);
if (!parsed) return res.status(400).json({ error: 'bad L402 header' });
const v = verifyMacaroon(parsed.macaroon, {
secret: process.env.L402_SECRET,
expectedScope: 'mcp-l402-gate:call',
});
if (!v.ok) return res.status(401).json({ error: v.reason });
if (!preimageMatchesHash(parsed.preimage, v.paymentHash)) {
return res.status(401).json({ error: 'preimage mismatch' });
}
const paid = await checkInvoicePaid(v.paymentHash, {
lnbitsUrl: process.env.LNBITS_URL,
lnbitsApiKey: process.env.LNBITS_INVOICE_KEY,
});
if (!paid) return res.status(402).json({ error: 'not yet paid' });
// caller is paid + macaroon is valid — proceed
Macaroon = base64url(JSON.stringify({
v: 1,
ph: <hex payment hash>,
sc: "<scope>",
exp: <unix seconds>,
cav: { ... },
sig: <hex hmac-sha256 over canonical JSON of body sans sig>
}))
Authorization: L402 <macaroon>:<preimage_hex>
This is the same wire format produced by @powforge/mcp-l402-gate@0.3+. If you mint with one and verify with the other, they will line up.
L402 is the Lightning Labs spec for using HTTP 402 + Lightning Network as the payment rail. The server returns WWW-Authenticate: L402 macaroon="...", invoice="...", the client pays the invoice, takes the preimage, and re-requests with Authorization: L402 <macaroon>:<preimage>. The server then verifies (1) the macaroon HMAC, (2) that sha256(preimage) == payment_hash, and (3) that the invoice actually settled on the Lightning Network.
This package implements step 3 against LNBits by default; pass your own checkPaidFn for any other Lightning backend (LND, Phoenix, Voltage, hosted).
Spec: https://docs.lightning.engineering/the-lightning-network/l402
The package is stateless by default. If you want replay protection, pass a usedSet (any object with .has(string) and .add(string) — a JS Set works). On a successful verifyL402 call, the preimage is added to the set. On any subsequent call with the same preimage, verification fails with reason: "preimage already redeemed".
For multi-process deployments, back the set with Redis or a database; the interface is just { has, add }.
MIT. PowForge.
FAQs
Standalone L402 (Lightning HTTP 402) payment verifier. Zero runtime dependencies. Parses Authorization: L402 <macaroon>: headers, verifies the HMAC-signed macaroon, checks sha256(preimage) === payment_hash, and confirms invoice settlement via LN
The npm package @powforge/l402-verify receives a total of 5 weekly downloads. As such, @powforge/l402-verify popularity was classified as not popular.
We found that @powforge/l402-verify demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.

Product
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.

Product
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.