Files
voidea/docs/backlog/oauth-schema-note.md
T

4.2 KiB
Raw Blame History

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;

Почему один провайдер

  1. Безопасность — меньше точек входа
  2. Простота — не нужно merge аккаунтов
  3. Ясность — пользователь знает что использует
  4. Privacy — данные не смешиваются между провайдерами

OAuth Flow

Яндекс

1. Пользователь нажимает "Войти через Яндекс"
2. Редирект на Яндекс OAuth
3. Callback с code
4. Получение access_token
5. Получение данных пользователя
6. Поиск/создание user по oauth_provider + oauth_id
7. Создание JWT session

Google

Аналогично Яндексу, с заменой 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.

Решение

  1. Email verification — требуется подтверждение
  2. Password check — для существующих пользователей
  3. 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