Назад до блогу

Чому 6-значні OTP-коди кращі за Magic Links у Next.js та Supabase: практичний гайд

Дізнайтеся, чому Magic Links програють одноразовим цифровим кодам та як налаштувати надійну OTP-авторизацію в Next.js і Supabase без помилок безпеки.

16 жовт. 2026 р.
7
напрямків
нотатки з delivery практики
3
рівні
стратегія · процес · інструменти
1
база
гайди · чеклісти · кейси
Переглянути кейси

Проблема традиційних Magic Links у сучасному вебі

Посилання для швидкої авторизації (Magic Links) тривалий час вважалися стандартом безпарольного входу. Проте на практиці цей механізм регулярно створює тертя для користувачів. Найпоширеніші сценарії збоїв включають роботу у внутрішніх браузерах соцмереж (in-app browsers), корпоративні поштові фільтри, які автоматично перевіряють та «спалюють» одноразові посилання ще до кліку, а також конфлікти відкриття у мобільних застосунках замість веб-інтерфейсу.

Використання 6-значного цифрового OTP-коду (One-Time Password) повністю усуває проблему deep link. Користувач залишається на тій самій сторінці чи екрані, переглядає код у повідомленні та просто вводить його у форму. Розглянемо правильну реалізацію цієї схеми в стеку Next.js (App Router) та Supabase.

Крок 1. Налаштування поштового шаблону в Supabase

За замовчуванням Supabase надсилає посилання з підтвердженням. Щоб змінити логіку на відправку коду, перейдіть до панелі керування проектом (Authentication → Email Templates → Magic Link) та замініть стандартний блок посилання на змінну токена {{ .Token }}.

Важливо переконатися, що у шаблоні не залишилося змінної {{ .ConfirmationURL }}, інакше поштовий клієнт отримає і посилання, і код, що заплутає користувача. Для продакшн-середовища обов'язково підключіть власний SMTP-провайдер (Resend, Postmark або AWS SES), оскільки вбудований поштовий сервіс має жорсткі ліміти відправки.

Крок 2. Серверний клієнт та обробка кукі

Для коректної роботи авторизації в середовищі Next.js App Router необхідно налаштувати серверний клієнт за допомогою бібліотеки @supabase/ssr. Це забезпечує надійне читання та оновлення авторизаційних cookies безпосередньо у серверних компонентах і Route Handlers.

Крок 3. Відправка коду та захист від перебору акаунтів

Ендпоінт генерації OTP повинен враховувати два критичні фактори безпеки:

  • Обмеження запитів (Rate Limiting) за IP: запобігає спаму поштовими запитами та перевитратам лімітів SMTP.
  • Захист від перебору адрес (Account Enumeration): сервер повинен повертати однаковий успішний статус незалежно від того, чи зареєстрований користувач із зазначеним email у базі.

Виклик функції supabase.auth.signInWithOtp з параметром shouldCreateUser: true відправляє 6-значний токен на пошту користувача або реєструє новий профіль, якщо обліковий запис ще не існує.

Крок 4. Верифікація коду з прив'язкою ліміту до Email

Шестизначний код має лише один мільйон комбінацій. За відсутності захисту зловмисник може перебрати валідний токен автоматизованим скриптом за лічені хвилини. Тому валідацію через supabase.auth.verifyOtp потрібно обмежувати строго за email-адресою, а не за IP, оскільки боти здатні легко змінювати IP-адреси.

Оптимальне обмеження — не більше 5 спроб введення на 10 хвилин для одного акаунта. Після успішної верифікації Supabase автоматично зберігає сесійні токени в HTTP-only cookies.

Крок 5. Актуалізація сесії через Middleware

Щоб користувач не втрачав авторизацію під час переходів між сторінками, у middleware.ts реалізується перевірка та автооновлення токенів. Важливе правило безпеки: для прийняття рішень щодо доступу на сервері завжди використовуйте метод supabase.auth.getUser(), оскільки він валідує актуальність користувача безпосередньо в базі даних, на відміну від локального читання cookie-сесії.

Висновки для бізнесу

Перехід на 6-значні цифрові коди підвищує коефіцієнт завершення реєстрації та зменшує кількість звернень до технічної підтримки через «непрацюючі посилання». Команда ViAcore рекомендує закладати надійне rate-limiting та захист сесій ще на етапі проектування архітектури, забезпечуючи швидкий і безпечний користувацький досвід.

Послуги з цієї теми

Потрібно таке для вашого проєкту?

Розробка під ключ: аналіз → реалізація → запуск → підтримка. Розкажіть про задачу — відповімо з оцінкою.

Про напрямок

Релевантні статті

Тестування REST та GraphQL контрактів у Cypress поруч із UI

Дізнайтеся, як перевірка API-контрактів поруч із UI-тестами в Cypress допомагає швидше знаходити помилки та підвищує надійність вебдодатків.

Сучасна архітектура статичних сайтів: як автоматизувати контроль якості та прискорити релізи

Як еволюція інструментів генерації статичних сторінок допомагає бізнесу прискорити релізи сайтів і гарантувати бездоганну якість коду перед публікацією.

Від прототипу до високих навантажень: як побудувати надійну LLM-архітектуру

Дізнайтеся, як побудувати відмовостійку архітектуру для AI-сервісів, уникнути збоїв під навантаженням та захистити бізнес-логіку застосунку.

Інтеграція локальних LLM у веб-додатки: альтернатива дорогим хмарним API

Дізнайтеся, як інтеграція локальних відкритих моделей штучного інтелекту допомагає бізнесу знизити витрати, гарантувати приватність даних і масштабувати веб-сервіси.

Тестування чорної скриньки: як перевірити сайт або сервіс очима користувача

Дізнайтеся, що таке тестування чорної скриньки (Black Box Testing), як воно допомагає бізнесу перевіряти цифрові продукти та чому захищає прибуток.

Безпека ШІ-інтеграцій: чому Prompt Injection не лікується як звичайна SQL-вразливість

Розбираємо, чому класичні методи захисту баз даних не працюють для мовних моделей і як побудувати безпечну архітектуру для ШІ-агентів.