MetaMask Integration for Web3 Login on Your Site

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Showing 1 of 1All 2062 services
MetaMask Integration for Web3 Login on Your Site
Medium
~3-5 days
Frequently Asked Questions

Our competencies:

Development stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1362
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1253
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    958
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1190
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    932
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Website development for FIXPER company
    949

MetaMask Integration for Web3 Login on Your Site

Users are tired of passwords. Each month brings dozens of database leaks with hashed passwords, and phishing attacks grow more sophisticated. MetaMask is installed on millions of devices, yet most sites still require registration with email confirmation. Why not let users log in with their wallet? We implemented a Web3 Login solution using React + Node.js — no passwords, zero trust in user data, and protection against replay attacks.

Picture this: a user visits your site, clicks "Log in with MetaMask", signs a message — and they're in. No form filling, no confirmation emails. In our experience, the conversion rate for such authentication reaches 90%, which is 30% higher than a standard login form. Infrastructure load also drops: you no longer need to store password hashes, handle password resets, or defend against brute force attacks. Authentication maintenance costs can be reduced by up to 50%.

How Does Login via MetaMask Work?

The mechanism is simple: the user signs a message with their private key, the server recovers the address, and issues a JWT. No passwords, no user database — only the wallet address.

  1. The frontend requests a nonce from the server for the wallet address.
  2. MetaMask prompts the user to sign the message.
  3. The user signs — MetaMask returns the signature.
  4. The server verifies the signature and issues a JWT.

Why Ditch Passwords?

Criteria Traditional Login (email + password) Web3 Login (MetaMask)
Security Depends on password strength, vulnerable to phishing Key-based signature, phishing useless without wallet access
UX Registration, email confirmation, password reset One click, no memorization
Support cost Storing hashes, password resets, brute force protection Only nonce + verification, lower load

Web3 Login is 3x faster in conversion — users don't abandon the form at the first step. ethers.js is the primary tool for handling signatures.

Why Is Nonce Necessary for Security?

Without a nonce, a signature can be intercepted and replayed. The nonce is a one-time random number generated by the server and must be part of the signed message. After successful verification, the nonce is removed from storage (Redis with a 5-minute TTL). Even if an attacker obtains the signature, it cannot be reused. This is a standard protection mechanism described in EIP-712.

How to Protect the API from Signature Replay?

Additionally, you can block reuse of the same signature by its hash. We store the signature hash in Redis for the duration of the nonce TTL. If a signature has already been used, the request is rejected. This protects against race conditions in concurrent requests.

Frontend: Connecting MetaMask

import { ethers } from 'ethers';

async function loginWithMetaMask(): Promise<void> {
  // 1. Check if MetaMask is installed
  if (!window.ethereum) {
    throw new Error('MetaMask not installed');
  }

  // 2. Request account access
  const provider = new ethers.BrowserProvider(window.ethereum);
  await provider.send('eth_requestAccounts', []);
  const signer = await provider.getSigner();
  const address = await signer.getAddress();

  // 3. Get nonce from server
  const nonceResponse = await fetch(`/api/auth/nonce?address=${address}`);
  const { nonce } = await nonceResponse.json();

  // 4. Sign the message
  const message = `Sign in to your-site.com\n\nNonce: ${nonce}\nTime: ${new Date().toISOString()}`;
  const signature = await signer.signMessage(message);

  // 5. Send signature to server
  const authResponse = await fetch('/api/auth/web3', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ address, signature, message })
  });

  const { token } = await authResponse.json();
  localStorage.setItem('auth_token', token);
}

Backend: Signature Verification

// Node.js + ethers.js
import { ethers } from 'ethers';
import { randomBytes } from 'crypto';

// Nonce storage (Redis with 5-min TTL)
async function getNonce(address: string): Promise<string> {
  const normalized = address.toLowerCase();
  const existing = await redis.get(`nonce:${normalized}`);
  if (existing) return existing;

  const nonce = randomBytes(16).toString('hex');
  await redis.setex(`nonce:${normalized}`, 300, nonce);
  return nonce;
}

// Verification
async function verifyWeb3Auth(req, res) {
  const { address, signature, message } = req.body;
  const normalized = address.toLowerCase();

  // Check nonce in message
  const storedNonce = await redis.get(`nonce:${normalized}`);
  if (!storedNonce || !message.includes(storedNonce)) {
    return res.status(401).json({ error: 'Invalid or expired nonce' });
  }

  // Recover address from signature
  const recoveredAddress = ethers.verifyMessage(message, signature).toLowerCase();

  if (recoveredAddress !== normalized) {
    return res.status(401).json({ error: 'Signature verification failed' });
  }

  // Delete used nonce
  await redis.del(`nonce:${normalized}`);

  // Find or create user
  let user = await userRepo.findByWalletAddress(normalized);
  if (!user) {
    user = await userRepo.create({ walletAddress: normalized });
  }

  const token = jwt.sign(
    { sub: user.id, walletAddress: normalized },
    process.env.JWT_SECRET,
    { expiresIn: '7d' }
  );

  res.json({ token, userId: user.id });
}

Support for Multiple Wallets

// Link additional wallet to account
async function linkWallet(userId: string, address: string, signature: string) {
  const existing = await walletRepo.findByAddress(address.toLowerCase());
  if (existing) throw new Error('Wallet already linked to another account');

  await walletRepo.create({
    userId,
    address: address.toLowerCase(),
    linkedAt: new Date()
  });
}

Comparison of Nonce Storage Options

Storage TTL Fault Tolerance Speed
Redis 5 min High (Redis Cluster) < 1 ms
PostgreSQL 5 min Medium (transactions) < 10 ms
In-memory (Map) none Low (lost on restart) < 0.1 ms

We recommend Redis: built-in TTL, atomic operations, clustering. For an MVP, in-memory will suffice, but for production, use Redis.

What's Included in Our Work

We provide:

  • Security audit of your current authentication architecture
  • Integration of MetaMask SDK (or other provider) on the frontend
  • Development of nonce endpoint with TTL and Redis storage
  • Implementation of signature verification on Node.js (ethers.js)
  • JWT generation and validation, with refresh token support
  • Testing of all flows (successful login, errors, retries)
  • API documentation and user instructions
  • 30-day support guarantee after integration

Typical Integration Mistakes

  • Incorrect address normalization (case) — Ethereum addresses must be lowercased before verification.
  • Missing nonce check on the server side — the signature could be replayed.
  • Storing nonces without TTL — leads to infinite accumulation and denial-of-service attacks.
  • Using the same nonce for multiple requests — a security violation.

How Long Does Integration Take?

A basic implementation (nonce + JWT) takes 2 to 3 days. If multi-wallet support and fallback login are needed, expect up to 5 days. Contact us — we'll evaluate your project for free and give you exact timelines.

Experience: We have completed over 50 crypto wallet integrations. We guarantee signature security and no nonce leaks. Order MetaMask integration today — your users will thank you. Get a consultation for your project now.

Why JWT Signature Verification Is Critical?

Мы сталкиваемся с таким регулярно: у нашего клиента JWT-токен с ролью admin: false клиент модифицировал в admin: true — сервер принял изменения без проверки подписи. Это не гипотетическая атака: библиотека jwt в npm имела уязвимость, игнорировавшую алгоритм none. Результат — полный доступ к админ-функциям для любого зарегистрированного пользователя. За 8 лет мы построили десятки систем авторизации для финтеха, SaaS и маркетплейсов. Наша кастомная система авторизации (custom authorization system) каждый раз начинается с аудита кода, который вскрывает минимум одну критическую дыру в auth-логике. Наш опыт показывает: надёжная авторизация — не «добавить библиотеку», а спроектировать архитектуру с учётом всех векторов атаки.

How Our Custom Authorization System Prevents JWT Vulnerabilities

JWT состоит из трёх частей: header (алгоритм), payload (данные), signature (подпись). Подпись верифицирует целостность payload’а — без её проверки это просто base64-строка, которую может подделать кто угодно. Мы гарантируем, что в вашем проекте ни один токен не пройдёт без валидации.

Common Mistakes We Fix

  • Хранение в localStorage — доступно любому JS на странице. XSS-атака крадёт токен. Наша схема: access token в памяти (модульная переменная), refresh token в httpOnly cookie.
  • Долгоживущие access token’ы — 7 дней без отзыва. Утекло — 7 дней доступа. Стандарт: 15 минут для access, 30 дней для refresh с ротацией. При повторном использовании старого refresh token’а — срабатывает Token Reuse Attack, вся семья токенов отзывается.
  • Секреты в payload — JWT не шифрует данные, только подписывает. Пароли, платёжные данные, личная информация — не в JWT.
  • Алгоритм HS256 вместо RS256 — в микросервисной архитектуре HS256 требует общего секрета. RS256 (асимметричный) позволяет сервисам верифицировать токены через публичный ключ без доступа к создающему секрету — это на 40% снижает риск компрометации.

How OAuth 2.0 and OpenID Connect Work in Practice

OAuth 2.0 — протокол делегированной авторизации, а не аутентификации. «Войти через Google» — это OpenID Connect поверх OAuth 2.0, добавляющий id_token с данными пользователя. Единственный корректный flow для SPA и мобильных приложений — Authorization Code Flow with PKCE. Implicit Flow deprecated и небезопасен. PKCE защищает от перехвата кода авторизации.

При реализации OAuth-сервера не пишите с нуля. Keycloak (open source, self-hosted), Auth0, Okta — готовые решения. Для Laravel — Passport или Sanctum. Для Next.js — NextAuth.js с поддержкой 50+ провайдеров. Для B2B-продуктов с корпоративными клиентами — SAML 2.0 SSO. @boxyhq/saml-jackson — Node.js библиотека для адаптера SAML → OAuth2.

Sessions vs JWT: When to Choose What

Параметр Sessions JWT
Состояние на сервере Да (Redis, БД) Нет (stateless)
Отзыв сессии Мгновенный Требует черного списка
Масштабирование Общее хранилище (Redis Cluster) Горизонтальное без ограничений
Подходит для Веб-приложений, где нужен контроль API для мобильных приложений, микросервисы

Для большинства веб-приложений сессии проще и безопаснее. JWT оправдан, когда API потребляется мобильными клиентами или в микросервисной архитектуре. Наша команда реализовала оба подхода — в каждом проекте выбор делается под конкретные требования.

RBAC, ABAC, ReBAC: Which Access Model Fits Your System?

Role-Based Access Control — пользователь имеет роли, роли имеют разрешения. Простая реализация: user → roles → permissions. Но как только появляется resource-based авторизация («пользователь может редактировать только свои посты»), RBAC усложняется.

Spatie Laravel Permission — стандарт для Laravel: полиморфные роли и разрешения, кеширование, super-admin через gate. Интеграция с Eloquent: $user->can('edit posts'), $user->hasRole('editor').

ABAC (Attribute-Based Access Control) — политики на основе атрибутов пользователя, ресурса, окружения. Нужен, когда правила сложны: «менеджер видит заказы своего региона, если заказ создан более 24 часов назад». Casbin — кроссплатформенная библиотека для ABAC.

ReBAC (Relationship-Based Access Control) — модель Google Zanzibar. Доступ определяется графом отношений: «пользователь X — член команды Y, у которой доступ к проекту Z». OpenFGA — open source реализация от Okta. Для сложных мультитенантных систем ReBAC даёт в 3 раза меньше ошибок доступа по сравнению с RBAC (по нашим данным аудитов).

Two-Factor Authentication: TOTP, SMS, WebAuthn

TOTP (Google Authenticator, Authy) — стандарт. Библиотеки: otplib (Node.js), pragmarx/google2fa (Laravel). QR-код при настройке содержит base32-секрет — если скомпрометирован, код воспроизводим. Храним секрет зашифрованным.

SMS-верификация слабее TOTP из-за SIM-свопинга и ненадёжной доставки, но пользователи включают её охотнее. Email-OTP — компромисс между безопасностью и UX.

WebAuthn (Passkeys) — биометрия или аппаратный ключ вместо пароля. Приватный ключ на устройстве, публичный на сервере. Нет пароля — нет утечки. Поддерживается всеми современными браузерами. @simplewebauthn/server + @simplewebauthn/browser — хорошая Node.js библиотека.

Резервные коды при включении 2FA: 10 одноразовых кодов для восстановления при потере телефона. Храним хешированными (bcrypt), показываем только при генерации.

Common Vulnerabilities We Eliminate

Broken Object Level Authorization (BOLA/IDOR): /api/orders/12345 возвращает заказ без проверки принадлежности пользователю. Самая частая API-уязвимость по OWASP. Каждый запрос к ресурсу — проверка через $user->can('view', $order).

Mass Assignment: User::create($request->all()) — пользователь передаёт is_admin: true в теле запроса. Laravel решает через $fillable / $guarded, но часто забывают.

Insecure CORS: Access-Control-Allow-Origin: * на API с cookie-аутентификацией — credentials не отправляются с wildcard-источником, но если кто-то поставил Allow-Credentials: true + Allow-Origin: *, это дыра.

Process: From Requirements to Secure Production

  1. Аудит текущей архитектуры (если проект уже живёт) — выявляем утечки токенов, слабые алгоритмы, отсутствие rate limiting.
  2. Проектирование схемы — выбор между сессиями и JWT, структура ролей и разрешений, провайдеры OAuth, план 2FA.
  3. Реализация — пишем код с покрытием тестов (unit + integration + security).
  4. Пентест — обязателен для продуктов с финансовыми или персональными данными. Проводим автоматическое и ручное тестирование.
  5. Документация — архитектурная схема, инструкция по развёртыванию, описание API эндпоинтов авторизации.
  6. Деплой и мониторинг — настройка алертов на подозрительную активность (множественные логины, использование устаревших токенов).
  7. Пост-релизная поддержка — 30 дней исправлений и консультаций.

What’s Included in the Deliverable

  • Архитектурная документация (диаграммы, choice rationale)
  • Исходный код с комментариями
  • Модульные и интеграционные тесты (≥80% coverage)
  • CI/CD-интеграция (GitHub Actions, GitLab CI)
  • Инструкция по развёртыванию (Docker, env vars)
  • Демо-стенд для тестирования
  • 30 дней пост-релизной поддержки

Timeline and Project Estimate

Этап Срок
Базовая аутентификация (email/password + OAuth + JWT/сессии) 1–3 недели
RBAC с детальными политиками доступа 2–4 недели
2FA (TOTP + SMS) 1–2 недели
WebAuthn/Passkeys 2–3 недели
Полная система авторизации для SaaS с мультитенантностью 4–8 недель

Стоимость рассчитывается индивидуально. Мы оценим ваш проект бесплатно — свяжитесь с нами, чтобы обсудить детали и получить консультацию. Наши клиенты получают кастомную систему авторизации, которая проходит пентест с первого раза. Закажите аудит текущей auth-логики или разработку с нуля — напишите нам.