Как реализовать авторизацию и обновление токена в Android приложениях
Что проверяют
Понимаете ли вы жизненный цикл токенов и умеете ли встроить обновление в сетевой слой так, чтобы параллельные запросы не ломали сессию. Следом обычно спрашивают, где хранить токены и что делать, когда истёк и refresh token.
Как отвечать
Схема стандартная для OAuth 2.0: короткоживущий access token идёт в каждом запросе, долгоживущий refresh token нужен только для получения новой пары. Вход через внешнего провайдера делают по Authorization Code с PKCE в Custom Tabs, а не во WebView.
Сетевой слой на OkHttp:
Interceptor: добавляет заголовокAuthorization: Bearer ...к каждому запросу;Authenticator: OkHttp вызывает его, когда сервер ответил401. Внутри обновите токен и верните копию запроса с новым заголовком, либоnull, если обновить не удалось;- одно обновление на всех: несколько запросов получают
401одновременно. Обновление держат под блокировкой и сначала сравнивают токен упавшего запроса с текущим: если его уже обновил другой поток, запрос просто повторяют; - отдельный клиент для refresh: запрос обновления идёт через
OkHttpClientбезAuthenticator, иначе получится рекурсия. Число попыток ограничивают черезresponse.priorResponse.
Если refresh вернул ошибку, сессия закончена: токены стираются, и приложение уводит пользователя на экран входа.
Хранение: SharedPreferences открытым текстом не годятся, а EncryptedSharedPreferences из security-crypto объявлены устаревшими. Современный вариант: DataStore плюс шифрование ключом из Android Keystore. Файл с токенами исключают из автобэкапа: ключи Keystore при восстановлении не переносятся, и расшифровать данные будет нечем.
Где спотыкаются
Обновляют токен в Interceptor на каждый 401 без синхронизации. При ротации refresh token второй запрос тратит уже недействительный токен, и пользователя выкидывает.
Оставляют HttpLoggingInterceptor в релизной сборке. Токены попадают в logcat, скрыть их можно через redactHeader("Authorization"), а лучше отключить логирование в релизе.
Кладут client_secret в APK или вызывают обновление через runBlocking на главном потоке. Секрет из APK достаётся за минуты, а блокировка UI даёт ANR.