Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Web3 Login Laravel Package

m1guelpf/laravel-web3-login

Add Web3 authentication to Laravel apps. Let users sign in by signing a message with their Ethereum wallet, then verify the signature and authenticate them—no passwords required. Simple setup for wallet-based login.

View on GitHub
Deep Wiki
Context7

Getting Started

This package adds Ethereum wallet authentication (Sign-In with Ethereum style) to a Laravel app: a user proves ownership of an address by signing a server-issued nonce, and the package verifies the signature and logs them in.

Minimal setup:

  1. composer require m1guelpf/laravel-web3-login
  2. Publish the config and migration: php artisan vendor:publish --tag=web3-login-config (and the migrations tag if you want the wallet_address column shipped with the package). Run php artisan migrate.
  3. Add the package trait to your App\Models\User (typically Web3Login) and ensure wallet_address is in $fillable.
  4. Check config/web3-login.php first — route prefix, middleware, nonce lifetime, and (from v1.1.0) the registration toggle are all there.
  5. Wire up the frontend: call the nonce/message endpoint, have the user sign with window.ethereum (personal_sign via ethers.js), then POST the signature back to the verification endpoint.

First real use case: gating a token-holders' area. A user connects MetaMask, signs a message, and lands on a dashboard behind auth middleware — no password ever typed.

As of v1.1.0, the first use case also includes onboarding brand-new users: if the signing address isn't attached to any user and registration is enabled, the package creates a User with the wallet address instead of rejecting the login. If you only want existing users to log in, explicitly disable that in config.

Implementation Patterns

Nonce-based challenge flow. Always treat the nonce as single-use and server-side. The canonical pattern is: request nonce → server stores it (session or cache keyed to the address) → user signs → verification consumes and invalidates it. Never let the client supply the nonce in the verification request.

Wallet-first registration (v1.1.0). For apps where the wallet is the identity, make email and password nullable and unique-index wallet_address. Then set the registration option so an unknown address creates a user. Pair this with an event/listener or model observer to send a welcome notification or provision a default workspace.

Hybrid auth. Keep email/password login intact and add wallet login as an additional route. A common pattern is a "link wallet" endpoint that reuses the same signature verification but attaches the address to auth()->user() instead of logging in — useful for existing accounts.

Custom user resolution. Override the user lookup in config or via a bound contract if you have multi-tenant users, soft-deleted users, or need to scope by guard/tenant before creating one.

Route protection and middleware. Apply auth to the app routes, and rate-limit the nonce and verification endpoints (throttle:10,1) — signature verification is cheap but the endpoints are publicly reachable.

Integration tips.

  • Normalize addresses to lowercase and store the EIP-55 checksummed form if you display them; compare with hash_equals on lowercased values.
  • If you're behind a SPA, use the session/cookie flow with Sanctum rather than fighting CORS with token-based wallet auth.
  • For tests, don't hit a live node: sign with a fixed private key using a small helper (e.g. ethers in a Node sidecar or a PHP secp256k1 lib) and post a deterministic signature. Keep the message string identical to what the package builds.
  • Listen for the login/registration event to log the address and IP for audit purposes.

Gotchas and Tips

The signed message must match byte-for-byte. A trailing newline, a different nonce casing, or an extra Address: line will make verification fail silently-ish. Log the exact message server-side when debugging.

Nonce replay and expiry. If your nonce lives in the session and the user opens a second tab, they'll clobber each other. Prefer a cache entry keyed by address with a short TTL (2–5 min) and delete on use.

Chain ID and domain binding. A signature is valid on any chain unless you bind it. Include the chain ID and your domain in the message so a signature harvested on a testnet or a lookalike domain can't be replayed. If you support multiple networks, validate the connected chain client-side and reject mismatches server-side.

Migration conflicts on existing apps. v1.1.0's registration path assumes wallet_address exists and is unique. On a live users table, add the column in your own migration (nullable()->unique()) rather than running the package's stub, and be aware SQLite and MySQL differ on how multiple NULL values interact with unique indexes — that's fine for MySQL/Postgres, but test on SQLite.

Registration can silently create accounts. Enabling wallet registration means anyone with a wallet can mint a User row. If your app assumes a password exists or sends email notifications, guard those paths — password will be null, and email will be null unless you collect it post-registration. Add a follow-up "complete your profile" step.

Guards and providers. The package logs in via the default guard. If you use a custom web3 guard or a separate members provider, point the config at the right guard, or the session will authenticate against the wrong model.

Extension points. The config file is the primary seam: route prefix, middleware stack, nonce TTL, registration toggle, and user model. Reach for container bindings only when config isn't enough — overridden lookup/creation logic is easier to test as a dedicated class than as a trait override.

Local development. Wallet extensions won't inject window.ethereum on plain HTTP from a non-localhost origin. Use php artisan serve on 127.0.0.1 with Hardhat/Anvil for a local chain, and test with the same account you use in your fixtures.

Debugging checklist, in order: does window.ethereum exist (HTTPS/localhost)? Is the signature the right v/s/r format? Does the recovered address match after lowercasing? Has the nonce already been consumed? Is the user found but the guard misconfigured?

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console