4.2 KiB
4.2 KiB
OAuth Schema - VoIdea
Дата: 2026-05-10 Статус: Backlog (для фиксации ADR)
Обзор
Схема авторизации: один пользователь = один провайдер. Нельзя привязать Google если уже есть Яндекс.
Правила
Основное правило
Один пользователь = один провайдер (email или OAuth)
Это означает:
- Если зарегистрировался через Яндекс → только Яндекс
- Если зарегистрировался через Google → только Google
- Если зарегистрировался через email → только email + пароль
Нельзя
- Привязать Google к аккаунту зарегистрированному через Яндекс
- Добавить второй OAuth провайдер
- Изменить email после регистрации через OAuth
Структура данных
Users table
CREATE TABLE users (
id UUID PRIMARY KEY,
email VARCHAR(255) UNIQUE,
password_hash VARCHAR(255), -- NULL если OAuth-only
-- OAuth данные (один провайдер)
oauth_provider VARCHAR(20), -- yandex|google|apple|null
oauth_id VARCHAR(255), -- ID в системе провайдера
-- Метаданные
email_verified BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
-- Constraints
CONSTRAINT users_oauth_xor_email CHECK (
(oauth_provider IS NOT NULL AND email IS NOT NULL) OR
(oauth_provider IS NULL AND email IS NOT NULL AND password_hash IS NOT NULL)
)
);
CREATE UNIQUE INDEX uq_users_oauth ON users(oauth_provider, oauth_id) WHERE oauth_provider IS NOT NULL;
Почему один провайдер
- Безопасность — меньше точек входа
- Простота — не нужно merge аккаунтов
- Ясность — пользователь знает что использует
- Privacy — данные не смешиваются между провайдерами
OAuth Flow
Яндекс
1. Пользователь нажимает "Войти через Яндекс"
2. Редирект на Яндекс OAuth
3. Callback с code
4. Получение access_token
5. Получение данных пользователя
6. Поиск/создание user по oauth_provider + oauth_id
7. Создание JWT session
Аналогично Яндексу, с заменой endpoint-ов.
Регистрация через email
-- При регистрации через email
INSERT INTO users (email, password_hash, oauth_provider, oauth_id)
VALUES ('user@example.com', 'hash123', NULL, NULL);
Вход через email
-- Проверка пароля
SELECT * FROM users WHERE email = 'user@example.com' AND password_hash = verify('hash123');
Защита от привязки чужого аккаунта
Проблема
Злоумышленник может попытаться привязать Google к чужому email.
Решение
- Email verification — требуется подтверждение
- Password check — для существующих пользователей
- Separate tables — OAuth и email разделены логически
Будущее (Apple OAuth)
Apple будет реализован позже
Для Apple потребуется:
- App Store Developer Account
- Private Key для подписи
- Тот же принцип: один пользователь = один провайдер
TODO
- Реализовать OAuth service
- Интегрировать Яндекс OAuth
- Интегрировать Google OAuth
- Зарезервировать место для Apple (не реализовывать)
- Тесты
- Документация
Создано: 2026-05-10 См. также: docs/adr/003-oauth-schema.md