For AI agents: fetch the complete documentation index at /llms.txt, the full documentation corpus at /llms-full.txt, the agent skill at /skill.md, or this page as Markdown at /ru/docs/mobile/passkeys.md (or send Accept: text/markdown).
Вход по ключу доступа
Беспарольный вход через передачу в браузер, возвращающую сессию в приложение.
Как работает передача в браузер
Вход по ключу доступа начинается в приложении и завершается в системном браузере. Приложение открывает {API URL}/auth?mobile_callback=<deep link> через WebBrowser.openAuthSessionAsync; после того как веб-страница завершает любой способ входа, она вызывает GET /api/auth/mobile-handoff, который перенаправляет обратно на <scheme>://auth/callback, перенося сессионную куки и одноразовый nonce состояния.
Каждая попытка генерирует свежий nonce, который должен вернуться без изменений — несовпадающий параметр state отклоняется как stateMismatch, поэтому устаревший или подделанный колбэк не может внедрить сессию. Возвращённая куки сливается в то же хранилище SecureStore, которое использует клиент Better Auth Expo (supastack.auth_cookie), затем хранилище сессии получает уведомление и рендерится приложение для вошедшего пользователя.
Закрытый пользователем браузерный лист разрешается в тихий результат cancelled, а не в ошибку, поэтому при нём оставляйте экран входа без изменений.
# apps/mobile/.env.local
EXPO_PUBLIC_APP_SCHEME=supastack
# apps/web/.env.local — server side
AUTH_PASSKEY_ENABLED=true
MOBILE_ALLOWED_ORIGINS=Держите список разрешённых одинаковым с обеих сторон
Обе стороны проверяют цель колбэка: приложение принимает только <scheme>://auth плюс настроенные production-источники, а сервер проверяет тот же список, построенный из EXPO_PUBLIC_APP_SCHEME и MOBILE_ALLOWED_ORIGINS. Колбэки с учётными данными, неизвестными схемами или похожими суффиксами отклоняются до того, как переместится любая куки.
В production MOBILE_ALLOWED_ORIGINS обязателен и должен перечислять точные нелокальные HTTPS-источники — подстановочные знаки не принимаются. Приложение поставляется в собранном виде, а сервер читает своё окружение при каждом запросе, поэтому смена схемы или источника требует и новой сборки приложения, и развёртывания сервера; изменение только одной стороны заставляет передачи завершаться отказом.
Остальные беспарольные способы
Тот же экран входа предлагает одноразовые коды по электронной почте (requestEmailOtp, затем verifyEmailOtp) и социальный вход через Apple или Google через signIn.social с callbackURL. Ключи доступа появляются, когда на сервере AUTH_PASSKEY_ENABLED=true; настройка ключей доступа и двухфакторной защиты аккаунта по-прежнему живёт в веб-приложении в разделе «Настройки → Безопасность».
Проверка и устранение неполадок
Отработайте колбэк холодного старта, возврат в работающее приложение, отменённый браузерный лист и истёкшую сессию на целевой сборке. Типизированные сбои — passkeyUnavailable, browserFailed, untrustedCallback, missingCookie, malformedCookie, cookieStoreFailed — каждый описывает отдельную поломку; stateMismatch означает, что nonce не вернулся и попытка была корректно отклонена.
Если каждая передача отклоняется, сравните EXPO_PUBLIC_APP_SCHEME в поставленной сборке со схемой сервера и MOBILE_ALLOWED_ORIGINS — пара расходится, когда одна сторона была передеплоена без другой.