Реалізація мультидевайсної авторизації в мобільному додатку
Multi-device login — можливість користувача бути залогіненим на кількох пристроях одночасно. iPhone, iPad, робочий Android — все показує актуальні дані. Технічно це історія про правильне управління токенами та синхронізацію стану між пристроями.
Архітектура токенів
Кожен пристрій отримує власну пару access_token + refresh_token. Backend зберігає таблицю сесій:
CREATE TABLE user_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id),
device_id VARCHAR(255) NOT NULL, -- унікальний ідентифікатор пристрою
device_name VARCHAR(255), -- "iPhone 15 Pro", "Samsung Galaxy S24"
device_type VARCHAR(50), -- ios, android, web
refresh_token_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMPTZ DEFAULT now(),
last_active_at TIMESTAMPTZ DEFAULT now(),
expires_at TIMESTAMPTZ NOT NULL,
UNIQUE(user_id, device_id)
);
device_id на Android — Settings.Secure.ANDROID_ID (не змінюється при переустановці, скидається при factory reset). На iOS — identifierForVendor (скидається при видаленні всіх додатків розробника). Для більш стабільного ID на iOS можна генерувати UUID при першому запуску та зберігати у Keychain.
device_name визначаємо з: Android — Build.MANUFACTURER + " " + Build.MODEL, iOS — UIDevice.current.name.
Обмеження кількості пристроїв
Деякі додатки обмежують кількість активних сесій (сервіси стрімінгу, фінансові додатки). При перевищенні ліміту backend повертає MAX_DEVICES_REACHED зі списком активних сесій — мобільний пропонує користувачу вибрати, яку сесію закрити.
sealed class LoginResult {
data class Success(val tokens: AuthTokens) : LoginResult()
data class MaxDevicesReached(val activeSessions: List<DeviceSession>) : LoginResult()
data class Error(val message: String) : LoginResult()
}
@Composable
fun MaxDevicesScreen(sessions: List<DeviceSession>, onRevoke: (String) -> Unit) {
Text("Досягнут ліміт пристроїв. Вийдіть з одного з них:")
sessions.forEach { session ->
DeviceSessionCard(
deviceName = session.deviceName,
lastActive = session.lastActiveAt,
onRevoke = { onRevoke(session.id) }
)
}
}
Синхронізація даних між пристроями
Коли користувач змінює дані на одному пристрої — інші повинні це дізнатися. Механізми:
Push-сповіщення з data payload — при зміні профілю на пристрої A, backend відправляє silent push на всі інші пристрої користувача. Пристрій B пробуджується, синхронізується у фоні.
WebSocket — якщо додаток використовує реалтайм, события синхронізації йдуть по тому ж каналу.
Pull при foreground — при виході з фону (onResume / applicationWillEnterForeground) запитуємо свіжі дані. Дешево реалізувати, підходить для рідких змін.
Для фінансових додатків — синхронізація балансу та історії транзакцій при кожному выході з фону обов'язкова. Кешований баланс на іншому пристрої повинен помічатися як stale після певного часу.
Реалізація multi-device login (кілька токенів, таблиця сесій, список пристроїв) — 2–3 тижні. З синхронізацією даних між пристроями — 3–5 тижнів. Вартість розраховується індивідуально.







