Реализация QR-кода для авторизации на другом устройстве
QR-авторизация — это когда пользователь уже залогинен в мобильном приложении, открывает веб-сайт или планшет, и вместо ввода пароля сканирует QR-код телефоном. Telegram Web, WhatsApp Web, Steam реализуют именно эту механику. Удобно и безопасно: credentials не вводятся на втором устройстве.
Протокол авторизации
Схема работает через временный challenge:
- Второе устройство (веб/планшет) запрашивает у backend одноразовый
session_tokenиqr_id. - Отображает QR-код с содержимым:
yourapp://qr-auth?token={session_token}. - Веб начинает polling или подписывается на WebSocket-событие по
qr_id. - Пользователь сканирует QR телефоном — приложение декодирует
session_token. - Телефон отправляет на backend: "Пользователь X авторизует сессию
session_token". - Backend проверяет, что
session_tokenсуществует и не истёк, создаёт сессию для второго устройства. - Второе устройство получает
access_tokenчерез WebSocket или следующий polling-запрос.
session_token живёт 2-5 минут. После использования — немедленно инвалидируется. Повторное использование невозможно.
Реализация на мобильном
Телефон сканирует QR и подтверждает авторизацию:
class QRAuthViewModel(
private val qrAuthRepository: QRAuthRepository,
private val cameraManager: CameraManager
) : ViewModel() {
fun onQRScanned(qrContent: String) {
val token = parseQRToken(qrContent) ?: run {
_state.value = QRAuthState.InvalidQR
return
}
// Показываем экран подтверждения до отправки запроса
_state.value = QRAuthState.ConfirmationRequired(token)
}
fun confirmAuthorization(token: String, deviceInfo: DeviceInfo) {
viewModelScope.launch {
_state.value = QRAuthState.Loading
qrAuthRepository.authorizeQRSession(
sessionToken = token,
deviceName = deviceInfo.name,
deviceType = deviceInfo.type
).fold(
onSuccess = { _state.value = QRAuthState.Authorized },
onFailure = { e ->
_state.value = when (e) {
is TokenExpiredException -> QRAuthState.QRExpired
is AlreadyUsedException -> QRAuthState.QRAlreadyUsed
else -> QRAuthState.Error(e.message)
}
}
)
}
}
}
Экран подтверждения — обязателен. Пользователь должен явно тапнуть "Войти", прежде чем сессия будет авторизована. Без этого шага — риск случайного сканирования чужого QR.
Генерация и отображение QR на втором устройстве
На веб-стороне QR обновляется по истечении — новый запрос к backend за свежим session_token. Анимированный таймер показывает, сколько осталось. По WebSocket: { event: "qr_authorized", accessToken: "..." } — мгновенная авторизация без перезагрузки страницы.
На планшете (мобильное второе устройство) — та же логика, только QR отображается через нативную библиотеку. На Android: zxing, на iOS: CIFilter.qrCodeGenerator.
Безопасность
QR-код содержит только временный токен — не credentials. Даже если кто-то сфотографировал QR — токен истечёт через минуты или уже использован. HTTPS обязателен для всех запросов. Backend проверяет, что session_token создан для того же user_id, что подтверждает телефон.
Реализация QR-авторизации (мобильный сканер + backend protocol + веб-сторона): 2-3 недели. Стоимость рассчитывается индивидуально.







