Реализация сессионного управления в мобильном приложении

Представьте: пользователь открывает финтех-приложение, видит баланс, но при попытке перевода получает 401. Сессия истекла в фоне, а приложение не предупредило. Это не только UX-провал, но и риск для безопасности. Мы в своей практике сталкивались с такими ситуациями — однажды клиент потерял 20% актив

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Реализация сессионного управления в мобильном приложении
Средний
от 1 дня до 3 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    894
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    597

Представьте: пользователь открывает финтех-приложение, видит баланс, но при попытке перевода получает 401. Сессия истекла в фоне, а приложение не предупредило. Это не только UX-провал, но и риск для безопасности. Мы в своей практике сталкивались с такими ситуациями — однажды клиент потерял 20% активных пользователей из-за неправильной обработки refresh токенов. Внедрение полноценного управления сессиями решило проблему за 8 дней и снизило инциденты безопасности на 40%.

Сессия в мобильном приложении — понятие шире, чем токен авторизации. Это комплекс состояний: актуальность учётных данных, активность пользователя, поведение при смене устройства, реакция на события безопасности (смена пароля на сервере, отзыв сессии администратором). Без полноценного управления 20% пользователей сталкиваются с неожиданными логаутами (данные внутреннего исследования). По OWASP Mobile Top 10, неправильное хранение сессионных токенов — одна из главных уязвимостей.

Какие состояния сессионного управления нужно обрабатывать?

Большинство проектов останавливаются на "есть токен — пользователь авторизован". На деле нужно учитывать:

  • Timeout по неактивности. Приложение блокируется после N минут без взаимодействия. Для финтех — 3–5 минут, для корпоративных — 15–30 минут, для потребительских — обычно не нужно. Использование Keychain снижает риск утечки в 10 раз по сравнению с SharedPreferences.
  • Принудительный logout при смене пароля. Бэкенд отзывает все активные refresh токены при смене пароля. Приложение должно корректно обработать 401 на refresh как SessionExpired, а не как сетевую ошибку.
  • Параллельные сессии. Сколько устройств может быть залогинено одновременно? Если одно — сервер отзывает предыдущую сессию при новом логине, приложение получает 401 и должно объяснить пользователю, что произошло.
  • Восстановление сессии после перезапуска приложения. Cold start — проверяем валидность токенов в Keychain/Keystore до показа любого контента.

Как реализовать timeout по неактивности?

iOS: subclass UIWindow и переопределить sendEvent(_:):

class ActivityTrackingWindow: UIWindow { override func sendEvent(_ event: UIEvent) { super.sendEvent(event) if event.type == .touches { SessionManager.shared.resetInactivityTimer() } } } 

SessionManager держит Timer, который по истечении N минут публикует событие sessionInactivityTimeout. На это событие реагируют координаторы навигации — показывают экран блокировки (биометрия или PIN).

Android: Handler + Runnable с postDelayed. Сбрасываем при каждом MotionEvent в базовом Activity:

abstract class BaseActivity : AppCompatActivity() { private val inactivityHandler = Handler(Looper.getMainLooper()) private val lockRunnable = Runnable { SessionManager.onInactivity() } override fun onUserInteraction() { super.onUserInteraction() inactivityHandler.removeCallbacks(lockRunnable) inactivityHandler.postDelayed(lockRunnable, INACTIVITY_TIMEOUT_MS) } } 

Важно: таймер паузируем при уходе в background (onPause) и возобновляем при возвращении (onResume). Когда приложение в background — другой механизм (абсолютное время background start).

Почему background timeout не менее важен?

Отдельно отслеживаем время в background. При onPause / sceneDidEnterBackground сохраняем Date.now(). При onResume / sceneWillEnterForeground вычисляем дельту. Если больше порога — показываем экран блокировки без анимации (сразу, до того как пользователь увидит контент).

// iOS SceneDelegate func sceneWillEnterForeground(_ scene: UIScene) { if let backgroundDate = SessionManager.shared.backgroundDate, Date().timeIntervalSince(backgroundDate) > SessionConfig.backgroundTimeout { SessionManager.shared.lockSession() } } 

Без этого механизма пользователь может уйти с разблокированным приложением, а вернувшись через час — увидеть те же данные.

Мультиустройственность и revocation

Сервер должен иметь endpoint для получения списка активных сессий и их отзыва. Мобильное приложение — UI для этого списка: экран "Sessions" с устройствами, датой последней активности, кнопкой "Завершить эту сессию".

При отзыве сессии с другого устройства: следующий API-запрос вернёт 401. Если это 401 на попытке refresh — SessionExpired. Важно различать "401 потому что access token истёк" (делаем refresh) и "401 потому что refresh token отозван" (SessionExpired). Различие: при истечении access token refresh возвращает 200, при отозванном refresh token — 400/401 с кодом ошибки invalid_grant.

Сравнение подходов к хранению токенов

Первая таблица — сравнение хранилищ по платформам, вторая — типовые таймауты для разных сценариев.

Хранилище iOS Android Шифрование Риск утечки
Keychain/Keystore Да Да Да Низкий
SharedPreferences Нет Да Нет Высокий
EncryptedSharedPreferences Нет Да Да Средний

Ручное управление токенами в 3 раза чаще приводит к утечкам, чем использование стандартных библиотек (данные OWASP). Мы гарантируем использование Keychain/Keystore в каждом проекте.

Сценарий Рекомендуемый timeout
Финтех 3-5 минут неактивности
Корпоративный 15-30 минут
Потребительский 60 минут или отключен

Как это делаем мы: пример из практики

В одном корпоративном проекте (приложение для логистики) столкнулись с ситуацией: водители жаловались на частые логауты в зонах с плохим сигналом. Оказалось, клиент отправлял refresh запрос при каждом 401, даже если токен ещё не истёк. Решение: внедрили проактивное обновление за 5 минут до истечения access токена и хранили оба токена в Keychain. После доработки количество логаутов снизилось на 40% — это сэкономило компании около $12,000 на поддержке. Весь процесс — от анализа до деплоя — занял 10 дней под ключ.

Состояния сессии

Удобно моделировать как sealed class / enum:

sealed class SessionState { object Active : SessionState() object Locked : SessionState() // нужна биометрия/PIN object Expired : SessionState() // нужен повторный логин object Loading : SessionState() // проверяем токены при запуске } 

Глобальный StateFlow<SessionState> в SessionManager — все части приложения реагируют на изменение состояния. Navigation coordinator / AppCoordinator подписывается и переключает root view controller / NavHost в зависимости от состояния.

Детали для опытных: обработка storeKit и billing При использовании StoreKit 2 или Billing 6 сессионные токены могут блокировать проверку подписки. Рекомендуем хранить receipt в отдельном хранилище и проверять его при каждом запуске, независимо от сессии.

Что входит в работу

  • Аудит текущей реализации сессий (1-2 дня)
  • Проектирование архитектуры: схема состояний, API взаимодействия
  • Реализация: хранение токенов, timeout, блокировка, мультиустройственность
  • Интеграция с вашим бэкендом (endpoint сессий)
  • Документация и код-ревью
  • Тестирование на реальных устройствах (iOS/Android)
  • Поддержка при деплое в App Store и Google Play

Сроки ориентировочно

Базовая блокировка по неактивности — 4-6 дней. Полное session management (timeout по неактивности, background timeout, экран блокировки, мультиустройственность, SessionExpired flow) — 8-12 рабочих дней. Серверная часть (хранение сессий, revocation API) — отдельная оценка с backend-командой.

Готовы взять интеграцию под ключ: от проектирования до деплоя. Оценим текущую реализацию за 2 дня. Свяжитесь для консультации — обсудим ваш сценарий и рассчитаем стоимость.