Розробка авторизації через гаманець (Sign-In with Ethereum)
Sign-In with Ethereum (SIWE, EIP-4361) — це стандарт аутентифікації де користувач підписує повідомлення своїм Ethereum гаманцем для входу в dApp. Без паролів, без email — лише криптографічна підпис. Це wallet-based auth, що став стандартом у Web3.
Як працює SIWE
- Backend генерує повідомлення з nonce
- Frontend показує повідомлення користувачу для підписання
- Користувач підписує через MetaMask/WalletConnect
- Backend верифікує підпис → видобуває адресу → створює сесію
Стандартний формат SIWE повідомлення:
app.example.com wants you to sign in with your Ethereum account:
0xYourAddress
Sign in to Example App
URI: https://app.example.com
Version: 1
Chain ID: 1
Nonce: abc123def456
Issued At: 2024-01-15T10:30:00.000Z
Expiration Time: 2024-01-15T11:30:00.000Z
Реалізація на бекенді (Node.js)
import { SiweMessage, generateNonce } from 'siwe';
import { ethers } from 'ethers';
// 1. Генерація nonce
app.get('/api/nonce', (req, res) => {
const nonce = generateNonce();
req.session.nonce = nonce;
res.json({ nonce });
});
// 2. Верифікація підпису
app.post('/api/verify', async (req, res) => {
const { message, signature } = req.body;
const siweMessage = new SiweMessage(message);
try {
const fields = await siweMessage.verify({
signature,
nonce: req.session.nonce,
domain: 'app.example.com'
});
// Підпис правильний — користувач володіє цією адресою
req.session.user = {
address: fields.data.address,
chainId: fields.data.chainId
};
res.json({ success: true, address: fields.data.address });
} catch (error) {
res.status(401).json({ error: 'Invalid signature' });
}
});
Реалізація на фронтенді з wagmi
import { useSignMessage, useAccount } from 'wagmi';
import { SiweMessage } from 'siwe';
function SignInButton() {
const { address } = useAccount();
const { signMessageAsync } = useSignMessage();
const handleSignIn = async () => {
// Отримати nonce від бекенду
const { nonce } = await fetch('/api/nonce').then(r => r.json());
// Сформувати SIWE повідомлення
const message = new SiweMessage({
domain: window.location.host,
address,
statement: 'Sign in to Example App',
uri: window.location.origin,
version: '1',
chainId: 1,
nonce,
});
// Підписати
const signature = await signMessageAsync({
message: message.prepareMessage()
});
// Верифікувати на бекенді
await fetch('/api/verify', {
method: 'POST',
body: JSON.stringify({ message: message.prepareMessage(), signature })
});
};
return <button onClick={handleSignIn}>Sign In with Ethereum</button>;
}
Захист від атак
Replay атаки: кожен nonce використовується один раз. Backend інвалідирує nonce після верифікації.
Фішинг: повідомлення повинно містити правильний домен. Користувач підписує саме для вашого домену, не для іншого.
Управління сесією: після SIWE створюється звичайна HTTP сесія (JWT, session cookie). SIWE — лише для початкової автентифікації, не для кожного запиту.
SIWE — золотий стандарт Web3 авторизації. Інтеграція з існуючим бекендом — 1-3 дні.







