From cf34ef64e4f53a51c5a7bc98834c08e285dd1090 Mon Sep 17 00:00:00 2001 From: faisalnugroho Date: Sat, 30 May 2026 22:29:22 +0800 Subject: [PATCH] fix(docs): add SIWE domain validation to authentication examples Fixes #1502 The backend verification examples only checked the cryptographic signature but not the SIWE message domain, making them vulnerable to cross-domain replay attacks. Changes: - Backend (Viem) example: Add parseSiweMessage and domain check - Express server example: Add parseSiweMessage import and domain check - Both examples now validate that the SIWE domain matches the expected host before accepting the signature This follows EIP-4361 requirements for domain validation. --- .../guides/authenticate-users.mdx | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/docs/base-account/guides/authenticate-users.mdx b/docs/base-account/guides/authenticate-users.mdx index 7a8332200..9510d14fb 100644 --- a/docs/base-account/guides/authenticate-users.mdx +++ b/docs/base-account/guides/authenticate-users.mdx @@ -147,11 +147,20 @@ try { ```ts Backend (Viem) import { createPublicClient, http } from 'viem'; import { base } from 'viem/chains'; +import { parseSiweMessage } from 'viem/siwe'; const client = createPublicClient({ chain: base, transport: http() }); export async function verifySig(req, res) { const { address, message, signature } = req.body; + + // 1. Validate SIWE domain to prevent cross-domain replay attacks + const siweMessage = parseSiweMessage(message); + if (siweMessage.domain !== 'yourapp.com') { + return res.status(400).json({ error: 'Domain mismatch' }); + } + + // 2. Verify signature const valid = await client.verifyMessage({ address, message, signature }); if (!valid) return res.status(401).json({ error: 'Invalid signature' }); // create session / JWT @@ -185,6 +194,7 @@ import crypto from "crypto"; import express from "express"; import { createPublicClient, http } from "viem"; import { base } from "viem/chains"; +import { parseSiweMessage } from "viem/siwe"; const app = express(); app.use(express.json()); @@ -209,11 +219,17 @@ app.post("/auth/verify", async (req, res) => { return res.status(400).json({ error: "Invalid or reused nonce" }); } - // 2. Verify signature + // 2. Validate SIWE domain to prevent cross-domain replay attacks + const siweMessage = parseSiweMessage(message); + if (siweMessage.domain !== 'yourapp.com') { + return res.status(400).json({ error: 'Domain mismatch' }); + } + + // 3. Verify signature const valid = await client.verifyMessage({ address, message, signature }); if (!valid) return res.status(401).json({ error: "Invalid signature" }); - // 3. Create session / JWT here + // 4. Create session / JWT here res.json({ ok: true }); });