fix(web3): normalize Ethereum addresses to lowercase to prevent case-…
fix(web3): normalize Ethereum addresses to lowercase to prevent case-sensitivity issues #2264
What kind of change does this PR introduce?
Bug fix - Resolves case-sensitivity issues with Ethereum addresses in SIWE (Sign-In with Ethereum) implementation.
What is the current behavior?
Ethereum addresses are stored with their original case (EIP-55 checksum format uses mixed case). This causes lookup failures when users sign in with a different case representation of the same address, as provider_id matching is case-sensitive.
What is the new behavior?
Ethereum addresses are now normalized to lowercase at parse time in parser.go. This ensures consistent storage and lookup regardless of the case used during sign-in.
Changes:
-
internal/utilities/siwe/parser.go- Normalize address to lowercase -
internal/utilities/siwe/parser_test.go- Update test expectations
Migration Notes
This fix applies to new signups only. Existing users with checksummed Ethereum addresses in provider_id may need manual migration.
For existing deployments with web3 users:
-- Check affected rows first
SELECT COUNT(*) FROM auth.identities
WHERE provider = 'web3'
AND provider_id LIKE 'web3:ethereum:0x%'
AND provider_id != LOWER(provider_id);
-- Normalize addresses to lowercase
UPDATE auth.identities
SET provider_id = LOWER(provider_id)
WHERE provider = 'web3'
AND provider_id LIKE 'web3:ethereum:0x%';
Note: For large tables, consider running in batches to avoid long locks.
Additional context
- Ethereum addresses are case-insensitive by design (EIP-55 uses mixed case only for checksum verification)
- The bulk migration was intentionally omitted per reviewer feedback to avoid performance issues on large
auth.identitiestables
Thanks for spotting the issue & contributing the fix @lingcoder !
Can you please also update the test?
https://github.com/supabase/auth/blob/9f39cade1df24634aff56facf06d8ebebfcec89b/internal/utilities/siwe/parser_test.go#L119
Hello! I reviewed this PR again and a quick note on the migration.
auth.identities can be massive on some projects, and the backfill UPDATE worries me (long run time, locks). We do have an index from UNIQUE (provider_id, provider), but since provider isn’t indexed on its own, WHERE provider = 'web3' can still end up doing a big scan.
What about skipping the bulk backfill and whoever needs backfilling can run manual queries?
Thanks for the feedback @cemalkilic! I've removed the bulk backfill migration as suggested. The code change will handle new signups automatically, and I've added migration notes in the PR description for existing deployments that may need to run manual queries.