Skip to content

feat: ERC-8128 authentication plugin#1

Closed
jacobot01 wants to merge 2 commits into
canaryfrom
erc8128
Closed

feat: ERC-8128 authentication plugin#1
jacobot01 wants to merge 2 commits into
canaryfrom
erc8128

Conversation

@jacobot01

@jacobot01 jacobot01 commented Mar 1, 2026

Copy link
Copy Markdown
Collaborator

feat(plugin): ERC-8128 authentication

Adds an erc8128() plugin that verifies ERC-8128 signed HTTP requests from Ethereum wallets (EOA and ERC-1271 smart contract accounts), built on RFC 9421 HTTP Message Signatures.

What it does

  • POST /erc8128/verify — verifies a signed request, creates/links user + wallet records, starts a Better Auth session.
  • hooks.before middleware — verifies Signature / Signature-Input headers on any BA endpoint, bridges into session resolution.
  • GET /.well-known/erc8128 — discovery metadata (OIDC/MCP pattern).
  • POST /erc8128/invalidate — revokes replayable signatures by key ID or individual signature (when allowReplayable: true).

Files

packages/better-auth/src/plugins/erc8128/
├── index.ts              # Plugin definition, endpoints, middleware
├── client.ts             # Client plugin (type inference)
├── schema.ts             # walletAddress + erc8128Invalidation tables
├── types.ts              # Shared types
├── utils.ts              # keyId parsing
├── nonce-store.ts        # DB-backed NonceStore (pluggable)
├── route-policy.ts       # Per-route auth policy resolution + wildcard matching
├── verification-cache.ts # Replayable signature cache (memory / DB / secondaryStorage)
├── erc8128.test.ts       # 27 test cases (vitest, getTestInstance harness)
└── nonce-store.test.ts   # Nonce store unit tests
docs/content/docs/plugins/erc8128.mdx  # Documentation page

Design decisions

Middleware model (like bearer): Translates verified signatures into session cookie context so getSession resolution works unchanged. Non-throwing on invalid headers — falls through to normal session/cookie auth.

Verification cache: Three-tier strategy based on what the host app provides: secondaryStorage (Redis) → DB (verification table) → in-memory Map. Pure performance optimization — cache miss triggers full cryptographic verification. Mirrors Better Auth's cookieCache philosophy.

Pluggable NonceStore, non-pluggable cache: Nonce storage needs strict guarantees (atomic consume, distributed consistency) so it's pluggable. The verification cache is deliberately non-authoritative — making it pluggable would add distributed-cache expectations Better Auth avoids.

User creation on /verify only: Middleware resolves existing wallet links but never creates users. Identity provisioning stays in the explicit auth endpoint where request body, onboarding policy, and response contracts are clear.

Route policy map: routePolicy option with "METHOD /path" keys and wildcard support, consistent with Better Auth's rateLimit.customRules pattern. false skips verification; a VerifyPolicy object requires it (structured 401 + Accept-Signature on failure).

Auth-only plugin: No bans, scoping, or rate limiting. Those belong in Better Auth's admin, access, and rate-limit layers.

Configuration

import { betterAuth } from "better-auth";
import { erc8128 } from "better-auth/plugins";
import { verifyMessage } from "viem";

export const auth = betterAuth({
  plugins: [
    erc8128({
      verifyMessage,
      allowReplayable: true,
      routePolicy: {
        "GET /api/products/*": { replayable: true },
        "GET /api/public/*": false,
        default: { replayable: false },
      },
    }),
  ],
});

Test coverage

27 tests covering: discovery, verify (user creation, linking, deduplication), middleware (auth header, passthrough, fallback), route policy (exact, wildcard, default, skip), invalidation (per-key, per-signature, cache eviction), replayable signatures (caching, expiry, sweep), and structured error responses.

References

@jacopo-eth jacopo-eth force-pushed the erc8128 branch 2 times, most recently from 1553feb to 679875c Compare March 4, 2026 14:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants