Files
lastochka-messenger/lastochka-ui/AUTH.md
Anton Budylin ea171ed95a first commit
2026-04-14 10:12:51 +03:00

9.4 KiB
Raw Blame History

Аутентификация в Ласточке

Обзор

Ласточка поддерживает два способа аутентификации:

  1. Классическая — логин и пароль
  2. По номеру телефона — SMS-код подтверждения

Регистрация по номеру телефона

Процесс регистрации

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
|  Ввод номера    | -> |  SMS с кодом     | -> |  Верификация    |
|  телефона       |    |  отправлено      |    |  завершена      |
└─────────────────┘    └──────────────────┘    └─────────────────┘

API

1. Отправка SMS для регистрации

import { useAuthStore } from '@/store/auth'

const { sendRegistrationSms } = useAuthStore()
await sendRegistrationSms('+7 (999) 999-99-99')

Что происходит:

  • Валидация номера телефона
  • Подключение к Tinode
  • Создание учётной записи с credential (номер телефона)
  • Отправка SMS кода подтверждения

2. Проверка SMS кода

const { verifyRegistrationSms } = useAuthStore()
await verifyRegistrationSms('123456', 'Имя пользователя')

Что происходит:

  • Проверка кода подтверждения
  • Создание полноценного аккаунта
  • Автоматический вход в систему

Утилиты для работы с телефоном

import { 
  formatPhoneNumber,      // Форматирование для отображения
  cleanPhoneNumber,       // Очистка для отправки на сервер
  isValidPhoneNumber,     // Валидация номера
} from '@/lib/phone-utils'

// Примеры
formatPhoneNumber('79999999999')     // "+7 (999) 999-99-99"
cleanPhoneNumber('+7 (999)...')      // "79999999999"
isValidPhoneNumber('+7 (999)...')    // true

Вход по номеру телефона

Процесс входа

import { useAuthStore } from '@/store/auth'

const { loginByPhone, loginWithSmsCode } = useAuthStore()

// 1. Запрос SMS кода
await loginByPhone('+7 (999) 999-99-99')

// 2. Ввод кода из SMS
await loginWithSmsCode('123456')

Классическая аутентификация

Вход по логину/паролю

const { login } = useAuthStore()
await login('username', 'password')

Регистрация по логину/паролю

// Пока не реализовано через отдельный метод
// Используйте login с новым логином

Компоненты

LoginScreen.tsx

Основной компонент экрана входа/регистрации.

Режимы работы:

  • phone-login — вход по номеру телефона
  • phone-register — регистрация по номеру телефона
  • login — вход по логину/паролю
  • register — регистрация по логину/паролю

Состояния:

  • verificationStep: 'none' — ввод номера/логина
  • verificationStep: 'sms-sent' — ожидание SMS кода
  • verificationStep: 'verified' — успешная верификация

SmsVerification.tsx

Компонент ввода SMS кода.

Props:

interface SmsVerificationProps {
  phone: string              // Номер телефона для отображения
  onComplete: (code) => void // Callback при вводе кода
  onBack: () => void         // Callback при возврате назад
  isLoading: boolean         // Индикатор загрузки
  error: string | null       // Сообщение об ошибке
  title?: string             // Заголовок
  description?: string       // Описание
}

Функции:

  • Автофокус на первом поле
  • Автопереход между полями
  • Поддержка вставки кода из буфера обмена
  • Обработка Backspace для возврата назад

Store (auth.ts)

Состояние

interface AuthState {
  isAuthenticated: boolean
  userId: string | null
  displayName: string | null
  isLoading: boolean
  error: string | null
  
  // Для SMS-верификации
  phoneForVerification: string | null
  verificationStep: 'none' | 'sms-sent' | 'verified'

  // Методы
  login: (login, password) => Promise<void>
  registerByPhone: (phone, displayName) => Promise<void>
  sendRegistrationSms: (phone) => Promise<void>
  verifyRegistrationSms: (code, displayName) => Promise<void>
  loginByPhone: (phone) => Promise<void>
  loginWithSmsCode: (code) => Promise<void>
  logout: () => Promise<void>
  tryAutoLogin: () => Promise<void>
}

SMS-провайдеры

Настройка

Для отправки SMS необходимо настроить SMS-провайдера на стороне сервера Tinode.

Популярные провайдеры для РФ:

  • SMS.ru
  • SMS Pilot
  • Prostor SMS
  • Telesign

Конфигурация на сервере

В конфигурации сервера Tinode укажите:

sms:
  provider: "sms.ru"
  api_key: "your-api-key"
  sender: "Lastochka"

Безопасность

Валидация номеров

  • Проверка формата российского номера (+7 XXX XXX-XX-XX)
  • Очистка от спецсимволов перед отправкой
  • Проверка длины номера (11 цифр)

Защита от злоупотреблений

  • Rate limiting на отправку SMS (не чаще 1 раза в минуту)
  • Максимум 3 попытки ввода кода
  • Блокировка при множественных неудачных попытках

Хранение токенов

  • Токен сохраняется в localStorage
  • Токен автоматически обновляется при продлении сессии
  • При logout токен удаляется

Пример использования

Полная регистрация по номеру телефона

import { useState } from 'react'
import { useAuthStore } from '@/store/auth'
import { formatPhoneNumber, isValidPhoneNumber } from '@/lib/phone-utils'

function RegistrationForm() {
  const [phone, setPhone] = useState('')
  const [displayName, setDisplayName] = useState('')
  const [code, setCode] = useState('')
  
  const { sendRegistrationSms, verifyRegistrationSms, isLoading, error } = useAuthStore()
  
  const handleSendSms = async () => {
    if (!isValidPhoneNumber(phone)) return
    await sendRegistrationSms(phone)
  }
  
  const handleVerify = async () => {
    await verifyRegistrationSms(code, displayName)
  }
  
  return (
    <form>
      <input
        type="tel"
        value={phone}
        onChange={(e) => setPhone(formatPhoneNumber(e.target.value))}
        placeholder="+7 (999) 999-99-99"
      />
      <input
        type="text"
        value={displayName}
        onChange={(e) => setDisplayName(e.target.value)}
        placeholder="Ваше имя"
      />
      <button onClick={handleSendSms} disabled={isLoading}>
        Получить код
      </button>
      
      <input
        type="text"
        value={code}
        onChange={(e) => setCode(e.target.value)}
        placeholder="Код из SMS"
        maxLength={6}
      />
      <button onClick={handleVerify} disabled={isLoading}>
        Подтвердить
      </button>
      
      {error && <p className="error">{error}</p>}
    </form>
  )
}

Интеграция с бэкендом

Эндпоинты

Сервер должен поддерживать следующие эндпоинты:

  1. POST /v1/creds/tel — запрос кода подтверждения
  2. PUT /v1/creds/tel — проверка кода подтверждения

Формат запроса

// Запрос SMS кода
{
  "tel": "79999999999",
  "op": "add"
}

// Проверка кода
{
  "tel": "79999999999",
  "val": "123456",
  "op": "add"
}

Формат ответа

{
  "code": 200,
  "text": "OK",
  "params": {
    "cred": "tel:79999999999"
  }
}

Тестирование

Тестовые номера

Для тестирования без реальной отправки SMS:

+7 (999) 000-00-01 → код: 123456
+7 (999) 000-00-02 → код: 654321

Mock SMS-провайдера

// В разработке можно использовать mock
export async function sendSmsCode(phone: string) {
  if (process.env.NODE_ENV === 'development') {
    console.log(`SMS код для ${phone}: 123456`)
    return { success: true }
  }
  // Реальная отправка SMS
}

Ласточка — народный мессенджер с открытым кодом 🕊️