Реалізація управління активними сесіями на розних пристроях
Екран управління сесіями — стандарт безпеки для мобільних додатків з чутливими даними. Користувач бачить, з яких пристроїв виконаний вхід, та може примусово завершити будь-яку сесію. Telegram, Google, банківські додатки — все реалізують цю функцію.
Що показувати користувачу
Для кожної активної сесії потрібен мінімальний контекст для ідентифікації пристрою:
- Назва пристрою та платформа ("iPhone 15 Pro, iOS 17.4")
- Приблизне місцезнаходження останнього входу за IP (GeoIP2 / ipapi)
- Дата та час останньої активності
- Поточний пристрій помічається окремо
data class DeviceSession(
val sessionId: String,
val deviceName: String,
val deviceType: DeviceType, // IOS, ANDROID, WEB
val location: String?, // "Москва, Росія"
val lastActiveAt: Instant,
val createdAt: Instant,
val isCurrentDevice: Boolean
)
Визначити поточний пристрій: при запиті списку сесій backend порівнює device_id з JWT з device_id кожної сесії. Поточний пристрій неможливо завершити з цього екрану — лише через явний logout.
UI екрану сесій
@Composable
fun ActiveSessionsScreen(
sessions: List<DeviceSession>,
onRevokeSession: (String) -> Unit,
onRevokeAll: () -> Unit
) {
LazyColumn {
item {
Text(
"Активні сесії",
style = MaterialTheme.typography.headlineSmall
)
}
items(sessions, key = { it.sessionId }) { session ->
SessionCard(
session = session,
onRevoke = if (session.isCurrentDevice) null
else {{ onRevokeSession(session.sessionId) }}
)
}
if (sessions.count { !it.isCurrentDevice } > 1) {
item {
TextButton(onClick = onRevokeAll) {
Text("Завершити всі інші сесії")
}
}
}
}
}
Відзив сесії
Завершення сесії: backend інвалідирує refresh_token (видаляє з таблиці або помічає як revoked). Пристрій з відозваною сесією при наступному запиті API або рефреші токена отримує 401. Мобільний обробляє 401 — переспрямовується на екран логіну та очищує локальні дані.
Для негайного ефекту (користувач опасається компрометації) потрібен більш агресивний механізм: при відзиві сесії backend відправляє silent push на цей пристрій з командою негайного logout. На Android — FCM data message з action: "force_logout". На iOS — APNs background notification з content-available: 1.
// Firebase Function: при відзиві сесії
async function revokeDeviceSession(sessionId: string, targetDeviceToken: string) {
await db.collection('sessions').doc(sessionId).update({ revoked: true });
await admin.messaging().send({
token: targetDeviceToken,
data: {
action: 'force_logout',
reason: 'session_revoked'
},
android: { priority: 'high' }
});
}
Сповіщення про нові входи
Безпечна практика: при вході з нового пристрою відправляти push-сповіщення на інші активні пристрої користувача: "Виконаний вхід на пристрої Samsung Galaxy S24 з Москви. Це були ви?" З кнопкою "Ні, завершити цю сесію".
Це стандарт безпеки у банків та фінтех-додатків. Реалізація: після створення нової сесії backend ітерує по решті fcm_token користувача та відправляє сповіщення.
Екран управління сесіями + сповіщення про нові входи + примусовий logout з push — 2–3 тижні. Вартість розраховується індивідуально.







