[PR #8575] feat: add ERC-8128 plugin #8073

Open
opened 2026-03-13 13:59:09 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/better-auth/better-auth/pull/8575
Author: @jacopo-eth
Created: 3/12/2026
Status: 🔄 Open

Base: canaryHead: feat/erc8128


📝 Commits (8)

📊 Changes

35 files changed (+10829 additions, -4 deletions)

View changed files

📝 .cspell/auth-terms.txt (+1 -0)
📝 .cspell/custom-words.txt (+2 -0)
docs/content/docs/plugins/erc8128.mdx (+642 -0)
📝 packages/better-auth/package.json (+9 -0)
📝 packages/better-auth/src/api/routes/session.ts (+7 -0)
📝 packages/better-auth/src/auth/base.ts (+20 -0)
📝 packages/better-auth/src/client/plugins/index.ts (+1 -0)
packages/better-auth/src/plugins/erc8128/cleanup.test.ts (+213 -0)
packages/better-auth/src/plugins/erc8128/cleanup.ts (+117 -0)
packages/better-auth/src/plugins/erc8128/client-utils.ts (+282 -0)
packages/better-auth/src/plugins/erc8128/client.ts (+305 -0)
packages/better-auth/src/plugins/erc8128/erc8128-client.test.ts (+1228 -0)
packages/better-auth/src/plugins/erc8128/erc8128.test.ts (+2879 -0)
packages/better-auth/src/plugins/erc8128/index.ts (+1521 -0)
packages/better-auth/src/plugins/erc8128/invalidation-store.test.ts (+446 -0)
packages/better-auth/src/plugins/erc8128/invalidation-store.ts (+774 -0)
packages/better-auth/src/plugins/erc8128/nonce-store.test.ts (+323 -0)
packages/better-auth/src/plugins/erc8128/nonce-store.ts (+252 -0)
packages/better-auth/src/plugins/erc8128/route-policy.test.ts (+184 -0)
packages/better-auth/src/plugins/erc8128/route-policy.ts (+240 -0)

...and 15 more files

📄 Description

Summary

This PR adds first-class ERC-8128 support to Better Auth.

ERC-8128 is a signature-based, Ethereum-native authentication primitive built on HTTP Message Signatures. Compared with SIWE, it does not center a login message flow first; instead, it lets clients sign individual requests directly with wallet signatures. That makes it a strong fit for human users, backend services and AI agents, while still allowing session-based UX where appropriate.

The goal of this plugin is to make compliant ERC-8128 usage feel native inside Better Auth by reusing existing Better Auth primitives for session issuance, request middleware, storage, user creation/linking, and route protection.

What’s Included

This PR adds a complete ERC-8128 integration across server, client, routing, and storage layers:

  • Server plugin with signature verification via user-provided verifyMessage
  • Two authentication modes:
    • session-based auth via /erc8128/verify
    • per-request authentication via Better Auth middleware and server helpers like protect() / verifyRequest()
  • Request protection helpers for arbitrary framework routes via:
    • auth.api.erc8128.protect(request)
    • auth.api.erc8128.verifyRequest(request)
    • auth.api.erc8128.getConfig(request?)
  • Automatic request-scoped identity resolution so Better Auth endpoints can treat the signer as the authenticated user for that request
  • Automatic wallet-user resolution / creation flows, including session bootstrap when using verify
  • Route-policy-based enforcement to declare:
    • which routes require ERC-8128 auth
    • whether replayable signatures are accepted
    • whether class-bound signatures are accepted
    • exact, wildcard, and default policy behavior
  • Built-in ERC-8128 endpoints:
    • /.well-known/erc8128
    • /erc8128/verify
    • /erc8128/invalidate
  • Client plugin (erc8128Client) that automatically signs Better Auth client requests
  • Client-side signature posture negotiation using the server discovery document
  • Replayable signature caching on the client when safe
  • Replay protection, invalidation, and verification caching on the server
  • Storage integration using Better Auth storage primitives:
    • secondaryStorage as the preferred fast path
    • optional DB persistence for security-critical nonce/invalidation records
    • cleanup support for expired ERC-8128 records
  • Tests covering server flows, client flows, route policy behavior, cache/invalidation behavior, and cleanup behavior
  • Documentation for setup, client usage, route protection, signing posture, route policy, storage, and custom endpoints

Why This Belongs in Better Auth

Better Auth already provides the right building blocks for this standard:

  • session creation and cookie management
  • request middleware and endpoint composition
  • shared storage abstractions
  • user/session typing
  • plugin and client extension points

This plugin builds on those primitives so users do not have to manually assemble a compliant ERC-8128 stack themselves. The result is a low-level signature-based auth primitive that still feels ergonomic and consistent with the rest of Better Auth.

Draft Review Focus

This is intentionally opened as a draft because I'm looking for early feedback on the implementation shape before treating the API and internals as settled. Specifically:

  • whether this is the right overall abstraction and API surface for Better Auth
  • whether the middleware / session / route-policy split is the right model
  • whether changes outside the erc812 plugin directory are required
  • whether the storage strategy is the best tradeoff between correctness and performance
  • whether we are minimizing DB round-trips as much as possible to keep request latency low
  • whether the replayable verification/invalidation paths are as efficient as they should be

In short: I want to validate both correctness and architecture, and make sure the final implementation is the most performant and maintainable approach we want to support long-term.

Docs / User-Facing Changes

  • Added ERC-8128 plugin documentation

Summary by cubic

Adds first-class ERC-8128 authentication to Better Auth with a server plugin, client plugin, built-in endpoints, route policies, and storage-backed replay protection and caching. Exposes typed helpers under auth.api.erc8128 and supports session login or per-request Ethereum-signed requests via erc8128Client.

  • New Features

    • Server plugin with verifyMessage and server API auth.api.erc8128: protect(request), verifyRequest(request), getConfig(request?).
    • Two modes: session via /erc8128/verify; per-request via helpers/middleware; invalidate via /erc8128/invalidate; discovery at /.well-known/erc8128.
    • Client plugin erc8128Client that signs requests, negotiates posture from server config, and caches replayable signatures when safe.
    • Route policy config (exact, wildcard, default) with per-method rules and replayable/class-bound controls; plugin endpoints auto-excluded.
    • Storage: nonce store, verification cache, invalidation store with cleanup scheduler; secondary storage fast path with setIfNotExists (supported in @better-auth/redis-storage and added to core SecondaryStorage); optional DB persistence.
    • Automatic wallet-user linking/creation and optional session bootstrap on verify; request-scoped identity resolution for Better Auth endpoints.
  • Migration

    • Enable the plugin: erc8128({ verifyMessage, routePolicy, ... }).
    • Configure secondary storage with setIfNotExists (e.g., @better-auth/redis-storage).
    • Optionally add DB models: erc8128Nonce, erc8128VerificationCache, erc8128Invalidation, walletAddress.
    • Add the client plugin: erc8128Client({ signer, fetch, storage }); use /erc8128/verify for session login or auth.api.erc8128.protect(request) / verifyRequest(request) for protected routes.

Written for commit b8406bcac3. Summary will update on new commits.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/better-auth/better-auth/pull/8575 **Author:** [@jacopo-eth](https://github.com/jacopo-eth) **Created:** 3/12/2026 **Status:** 🔄 Open **Base:** `canary` ← **Head:** `feat/erc8128` --- ### 📝 Commits (8) - [`f56fe3e`](https://github.com/better-auth/better-auth/commit/f56fe3e779dd50b3391410f67ec2cf3b6381cb1f) feat: erc8128 plugin - [`084a8a7`](https://github.com/better-auth/better-auth/commit/084a8a748d9cc8e3c178367aebd70f7208c6319e) Merge branch 'canary' into erc8128 - [`6ad9cba`](https://github.com/better-auth/better-auth/commit/6ad9cbaa0b4efe6e7a0f520352a2e1ad4f7c1f72) fix - [`45d7bdd`](https://github.com/better-auth/better-auth/commit/45d7bddf528f81511402a58ce1627106682315a7) fix: review comments - [`c7faefa`](https://github.com/better-auth/better-auth/commit/c7faefa76bf5b1f99f61cba2b64d7f9f06057cb1) nit: format - [`94756c4`](https://github.com/better-auth/better-auth/commit/94756c401413042df5707a5eb4c3a6b8024e2883) nit: format - [`c56090a`](https://github.com/better-auth/better-auth/commit/c56090a75366a30b7131c46f26356b76c242f854) nit: format - [`b8406bc`](https://github.com/better-auth/better-auth/commit/b8406bcac3d5d931b3d33aefbd9a625d95ec474f) nit: format ### 📊 Changes **35 files changed** (+10829 additions, -4 deletions) <details> <summary>View changed files</summary> 📝 `.cspell/auth-terms.txt` (+1 -0) 📝 `.cspell/custom-words.txt` (+2 -0) ➕ `docs/content/docs/plugins/erc8128.mdx` (+642 -0) 📝 `packages/better-auth/package.json` (+9 -0) 📝 `packages/better-auth/src/api/routes/session.ts` (+7 -0) 📝 `packages/better-auth/src/auth/base.ts` (+20 -0) 📝 `packages/better-auth/src/client/plugins/index.ts` (+1 -0) ➕ `packages/better-auth/src/plugins/erc8128/cleanup.test.ts` (+213 -0) ➕ `packages/better-auth/src/plugins/erc8128/cleanup.ts` (+117 -0) ➕ `packages/better-auth/src/plugins/erc8128/client-utils.ts` (+282 -0) ➕ `packages/better-auth/src/plugins/erc8128/client.ts` (+305 -0) ➕ `packages/better-auth/src/plugins/erc8128/erc8128-client.test.ts` (+1228 -0) ➕ `packages/better-auth/src/plugins/erc8128/erc8128.test.ts` (+2879 -0) ➕ `packages/better-auth/src/plugins/erc8128/index.ts` (+1521 -0) ➕ `packages/better-auth/src/plugins/erc8128/invalidation-store.test.ts` (+446 -0) ➕ `packages/better-auth/src/plugins/erc8128/invalidation-store.ts` (+774 -0) ➕ `packages/better-auth/src/plugins/erc8128/nonce-store.test.ts` (+323 -0) ➕ `packages/better-auth/src/plugins/erc8128/nonce-store.ts` (+252 -0) ➕ `packages/better-auth/src/plugins/erc8128/route-policy.test.ts` (+184 -0) ➕ `packages/better-auth/src/plugins/erc8128/route-policy.ts` (+240 -0) _...and 15 more files_ </details> ### 📄 Description ## Summary This PR adds first-class ERC-8128 support to Better Auth. ERC-8128 is a signature-based, Ethereum-native authentication primitive built on HTTP Message Signatures. Compared with SIWE, it does not center a login message flow first; instead, it lets clients sign individual requests directly with wallet signatures. That makes it a strong fit for human users, backend services and AI agents, while still allowing session-based UX where appropriate. The goal of this plugin is to make compliant ERC-8128 usage feel native inside Better Auth by reusing existing Better Auth primitives for session issuance, request middleware, storage, user creation/linking, and route protection. ## What’s Included This PR adds a complete ERC-8128 integration across server, client, routing, and storage layers: - Server plugin with signature verification via user-provided `verifyMessage` - Two authentication modes: - session-based auth via `/erc8128/verify` - per-request authentication via Better Auth middleware and server helpers like protect() / verifyRequest() - Request protection helpers for arbitrary framework routes via: - `auth.api.erc8128.protect(request)` - `auth.api.erc8128.verifyRequest(request)` - `auth.api.erc8128.getConfig(request?)` - Automatic request-scoped identity resolution so Better Auth endpoints can treat the signer as the authenticated user for that request - Automatic wallet-user resolution / creation flows, including session bootstrap when using verify - Route-policy-based enforcement to declare: - which routes require ERC-8128 auth - whether replayable signatures are accepted - whether class-bound signatures are accepted - exact, wildcard, and default policy behavior - Built-in ERC-8128 endpoints: - `/.well-known/erc8128` - `/erc8128/verify` - `/erc8128/invalidate` - Client plugin (`erc8128Client`) that automatically signs Better Auth client requests - Client-side signature posture negotiation using the server discovery document - Replayable signature caching on the client when safe - Replay protection, invalidation, and verification caching on the server - Storage integration using Better Auth storage primitives: - `secondaryStorage` as the preferred fast path - optional DB persistence for security-critical nonce/invalidation records - cleanup support for expired ERC-8128 records - Tests covering server flows, client flows, route policy behavior, cache/invalidation behavior, and cleanup behavior - Documentation for setup, client usage, route protection, signing posture, route policy, storage, and custom endpoints ## Why This Belongs in Better Auth Better Auth already provides the right building blocks for this standard: - session creation and cookie management - request middleware and endpoint composition - shared storage abstractions - user/session typing - plugin and client extension points This plugin builds on those primitives so users do not have to manually assemble a compliant ERC-8128 stack themselves. The result is a low-level signature-based auth primitive that still feels ergonomic and consistent with the rest of Better Auth. ## Draft Review Focus This is intentionally opened as a draft because I'm looking for early feedback on the implementation shape before treating the API and internals as settled. Specifically: - whether this is the right overall abstraction and API surface for Better Auth - whether the middleware / session / route-policy split is the right model - whether changes outside the erc812 plugin directory are required - whether the storage strategy is the best tradeoff between correctness and performance - whether we are minimizing DB round-trips as much as possible to keep request latency low - whether the replayable verification/invalidation paths are as efficient as they should be In short: I want to validate both correctness and architecture, and make sure the final implementation is the most performant and maintainable approach we want to support long-term. ## Docs / User-Facing Changes - Added ERC-8128 plugin documentation <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Adds first-class ERC-8128 authentication to Better Auth with a server plugin, client plugin, built-in endpoints, route policies, and storage-backed replay protection and caching. Exposes typed helpers under `auth.api.erc8128` and supports session login or per-request Ethereum-signed requests via `erc8128Client`. - **New Features** - Server plugin with `verifyMessage` and server API `auth.api.erc8128`: `protect(request)`, `verifyRequest(request)`, `getConfig(request?)`. - Two modes: session via `/erc8128/verify`; per-request via helpers/middleware; invalidate via `/erc8128/invalidate`; discovery at `/.well-known/erc8128`. - Client plugin `erc8128Client` that signs requests, negotiates posture from server config, and caches replayable signatures when safe. - Route policy config (exact, wildcard, default) with per-method rules and replayable/class-bound controls; plugin endpoints auto-excluded. - Storage: nonce store, verification cache, invalidation store with cleanup scheduler; secondary storage fast path with `setIfNotExists` (supported in `@better-auth/redis-storage` and added to core `SecondaryStorage`); optional DB persistence. - Automatic wallet-user linking/creation and optional session bootstrap on verify; request-scoped identity resolution for Better Auth endpoints. - **Migration** - Enable the plugin: `erc8128({ verifyMessage, routePolicy, ... })`. - Configure secondary storage with `setIfNotExists` (e.g., `@better-auth/redis-storage`). - Optionally add DB models: `erc8128Nonce`, `erc8128VerificationCache`, `erc8128Invalidation`, `walletAddress`. - Add the client plugin: `erc8128Client({ signer, fetch, storage })`; use `/erc8128/verify` for session login or `auth.api.erc8128.protect(request)` / `verifyRequest(request)` for protected routes. <sup>Written for commit b8406bcac3d5d931b3d33aefbd9a625d95ec474f. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-03-13 13:59:09 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#8073