Перейти к основному содержимому

Аутентификация API

Руководство по аутентификации в API платформы.

Типы аутентификации

JWT токены

Основной метод аутентификации - JSON Web Tokens:

// Получение токена при входе
const { data, error } = await supabase.auth.signInWithPassword({
email: 'user@example.com',
password: 'password'
});

const token = data.session?.access_token;

API ключи

Для серверных интеграций:

const headers = {
'apikey': 'your-service-role-key',
'Authorization': 'Bearer your-service-role-key'
};

Структура токена

JWT токен содержит:

{
"sub": "user-uuid",
"email": "user@example.com",
"role": "authenticated",
"tenant_id": "tenant-uuid",
"marketplace_role": "supplier",
"exp": 1234567890,
"iat": 1234567890
}

Аутентификация в маркетплейсе

Регистрация пользователя маркетплейса

// Edge Function: marketplace-auth-register
const response = await fetch('/functions/v1/marketplace-auth-register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${anonKey}`
},
body: JSON.stringify({
tenantId: 'marketplace-uuid',
email: 'user@example.com',
password: 'secure-password',
role: 'customer', // или 'supplier'
firstName: 'Иван',
lastName: 'Петров'
})
});

Вход в маркетплейс

// Edge Function: marketplace-auth-login
const response = await fetch('/functions/v1/marketplace-auth-login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${anonKey}`
},
body: JSON.stringify({
tenantId: 'marketplace-uuid',
email: 'user@example.com',
password: 'password'
})
});

const { user, sessionToken, expiresAt } = await response.json();

Подтверждение email

Отправка кода подтверждения

// Автоматически при регистрации через Edge Function
const confirmationCode = await generateConfirmationCode();
await sendConfirmationEmail(email, confirmationCode);

Подтверждение кода

// Edge Function: marketplace-auth-confirm
const response = await fetch('/functions/v1/marketplace-auth-confirm', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${anonKey}`
},
body: JSON.stringify({
tenantId: 'marketplace-uuid',
email: 'user@example.com',
code: '123456'
})
});

Refresh токены

Автоматическое обновление токенов:

const { data, error } = await supabase.auth.refreshSession();
if (data.session) {
const newToken = data.session.access_token;
}

Роли и права доступа

Системные роли

  • super_admin - полный доступ к системе
  • admin - управление конкретным маркетплейсом
  • authenticated - авторизованный пользователь

Роли маркетплейса

  • client - владелец маркетплейса
  • supplier - поставщик товаров/услуг
  • customer - покупатель

Проверка ролей в RLS

-- Проверка системной роли
CREATE FUNCTION has_role(required_role app_role, tenant_uuid UUID DEFAULT NULL)
RETURNS BOOLEAN AS $$
BEGIN
RETURN EXISTS (
SELECT 1 FROM user_roles
WHERE user_id = auth.uid()
AND role = required_role
AND (tenant_id = tenant_uuid OR tenant_uuid IS NULL)
);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Проверка роли в маркетплейсе
CREATE FUNCTION has_marketplace_role(tenant_uuid UUID, user_email TEXT, required_role marketplace_role)
RETURNS BOOLEAN AS $$
BEGIN
RETURN EXISTS (
SELECT 1 FROM marketplace_users
WHERE tenant_id = tenant_uuid
AND email = user_email
AND role = required_role
AND is_active = true
);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

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

Защита от CSRF

Все запросы должны включать CSRF токен:

const csrfToken = await getCsrfToken();
const headers = {
'X-CSRF-Token': csrfToken,
'Authorization': `Bearer ${token}`
};

Rate Limiting

Ограничения по ролям:

  • Анонимные пользователи: 10 запросов/минуту
  • Авторизованные: 100 запросов/минуту
  • Поставщики: 500 запросов/минуту
  • Администраторы: без ограничений

IP Whitelist

Для критичных операций можно настроить белый список IP:

CREATE TABLE ip_whitelist (
id UUID PRIMARY KEY,
user_id UUID REFERENCES auth.users(id),
ip_address INET NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT NOW()
);

Обработка ошибок аутентификации

Коды ошибок

  • 401 - Неверные учетные данные
  • 403 - Недостаточно прав
  • 422 - Требуется подтверждение email
  • 429 - Превышен лимит запросов

Примеры ошибок

{
"error": {
"code": "INVALID_CREDENTIALS",
"message": "Неверный email или пароль"
}
}
{
"error": {
"code": "EMAIL_NOT_CONFIRMED",
"message": "Необходимо подтвердить email",
"needsConfirmation": true
}
}

Выход из системы

Стандартный выход

const { error } = await supabase.auth.signOut();

Выход из маркетплейса

// Очистка локального хранилища
localStorage.removeItem('marketplace_session');
localStorage.removeItem('marketplace_user');

// Редирект на страницу входа
navigate('/auth');

Многофакторная аутентификация (MFA)

Настройка TOTP

const { data, error } = await supabase.auth.mfa.enroll({
factorType: 'totp'
});

const qrCode = data.totp.qr_code;
const secret = data.totp.secret;

Проверка MFA

const { data, error } = await supabase.auth.mfa.verify({
factorId: factorId,
challengeId: challengeId,
code: '123456'
});

Лучшие практики

  1. Короткий срок жизни токенов - максимум 1 час
  2. Безопасное хранение - никогда не храните токены в localStorage
  3. HTTPS везде - все запросы только через защищенное соединение
  4. Валидация на клиенте и сервере - двойная проверка
  5. Логирование входов - аудит всех попыток аутентификации
  6. Автоматический выход - при длительном бездействии

Интеграция с внешними провайдерами

Google OAuth

const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: `${window.location.origin}/auth/callback`
}
});

Яндекс OAuth

const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'yandex',
options: {
redirectTo: `${window.location.origin}/auth/callback`
}
});