Как прикрутить вход через Apple в React Native и не сойти с ума

16 авг 2026

Репозиторий давно не обновлялся

Последнее обновление было 8 месяцев назад.

1,665
235
14
8 месяцев

Если вы когда-нибудь выкатывали мобильное приложение с авторизацией через Google или соцсети в App Store, вы наверняка сталкивались с жестким правилом ревьюеров: добавил сторонний вход — изволь поставить Sign In with Apple. Иначе реджект прилетит быстрее, чем соберется релизный билд.

Казалось бы, задача тривиальная. Но когда начинаешь разбираться с нативными вызовами, спецификой работы на симуляторах и причудами яблочного API, вылезает масса подводных камней. Ребята из команды Invertase (те самые, кто делает React Native Firebase) написали библиотеку react-native-apple-authentication, которая закрывает этот вопрос как для iOS, так и для Android.

apple-auth

Что под капотом и зачем это нужно

Библиотека дает полный доступ к яблочному механизму аутентификации. Работает на чистом React Native от версии 0.60, дружит с Expo (через prebuild и конфиг entitlements в app.json), поддерживает macOS и даже умеет авторизовывать пользователей на Android через браузерный flow.

Самое приятное тут — типизация из коробки и готовый нативный компонент кнопки AppleButton. Дизайн кнопки строго регламентирован гайдлайнами Apple. Если нарисовать ее отсебятиной, ревьюеры с удовольствием завернут приложение. Здесь же стили и локализация подтягиваются прямо из нативной системы.

Реклама

Как устроен базовый сценарий на iOS

Установка стандартная: ставим пакет через yarn или npm, в папке ios прогоняем pod install. Модуль поддерживает автолинкинг, поэтому копаться в AppDelegate не придется.

Для кнопки и логики входа хватает буквально пары импортов:

import React from 'react';
import { View } from 'react-native';
import { AppleButton, appleAuth } from '@invertase/react-native-apple-authentication';

export function LoginScreen() {
  async function handleAppleLogin() {
    // Запускаем нативный запрос авторизации
    const authResponse = await appleAuth.performRequest({
      requestedOperation: appleAuth.Operation.LOGIN,
      // Порядок скоупов имеет значение
      requestedScopes: [appleAuth.Scope.FULL_NAME, appleAuth.Scope.EMAIL],
    });

    // Проверяем статус пользователя
    const credentialState = await appleAuth.getCredentialStateForUser(authResponse.user);

    if (credentialState === appleAuth.State.AUTHORIZED) {
      // Пользователь подтвержден, отправляем токены на бэкенд
      console.log('User ID:', authResponse.user);
      console.log('Identity Token:', authResponse.identityToken);
    }
  }

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <AppleButton
        buttonStyle={AppleButton.Style.BLACK}
        buttonType={AppleButton.Type.SIGN_IN}
        style={{ width: 200, height: 45 }}
        onPress={handleAppleLogin}
      />
    </View>
  );
}

Грабли, на которые наступают все новички

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

Имя и почта приходят только один раз

Apple помешана на приватности. При первом входе пользователь может выбрать, скрыть реальную почту или показать. Данные профиля (fullName и email) нативный фреймворк отдаст ровно один раз — во время самой первой успешной авторизации.

При повторных вызовах эти поля придут пустыми (null). Если вы не сохранили имя и email в свою базу сразу, получить их заново через клиентский API не выйдет.

Чтобы сбросить тестовое состояние на айфоне и снова получить профиль, приходится лезть руками в системные настройки: Настройки > Apple ID > Пароль и безопасность > Приложения, использующие Apple ID, удалять там свое тестовое приложение и логиниться заново.

Кстати, в репозитории проекта отдельно подмечен баг самого яблочного API: скоупы нужно передавать именно в порядке [FULL_NAME, EMAIL]. Если поменять местами, имя может потеряться уже на первом запросе.

Симуляторы и ошибка 1000

Метод getCredentialStateForUser проверяет подлинность девайса. На симуляторе iOS он регулярно падает с ошибкой com.apple.AuthenticationServices.AuthorizationError error 1000. Полноценно протестировать цепочку авторизации получится только на физическом устройстве.

Если симулятор намертво заклинило на этой ошибке, разработчики советуют зайти на сайт управления Apple ID, найти там список привязанных устройств и выкинуть симулятор из аккаунта.

show-devices

remove-from-manager

Логаут — это фикция

В перечислениях модуля есть операция appleAuth.Operation.LOGOUT, но на практике в нативном iOS SDK она ничего не делает. Apple не предоставляет метода принудительного разлогина из системы на уровне устройства. Логаут на клиенте сводится к тому, что вы просто стираете локальную сессию, сохраненные токены и очищаете стейт приложения.

Отзыв доступа

Пользователь может в любой момент зайти в настройки iOS и отозвать разрешение на вход для вашей программы. Чтобы вовремя среагировать и выкинуть юзера на экран логина, в библиотеке есть слушатель событий:

useEffect(() => {
  const unsubscribe = appleAuth.onCredentialRevoked(async () => {
    // Токены больше не валидны, сбрасываем локальное состояние
    console.warn('Доступ отозван пользователем в настройках Apple ID');
  });

  return () => unsubscribe();
}, []);

Что делать с Android

Многие удивляются, но пускать через Apple ID можно и пользователей Android. Механика там другая: вместо нативного фреймворка открывается защищенное окно браузера через OAuth 2.0 Web Flow.

Библиотека берет рутину на себя через модуль appleAuthAndroid:

import { appleAuthAndroid } from '@invertase/react-native-apple-authentication';
import 'react-native-get-random-values';
import { v4 as uuid } from 'uuid';

async function handleAndroidAppleLogin() {
  const rawNonce = uuid();
  const state = uuid();

  appleAuthAndroid.configure({
    clientId: 'com.example.client-android', // Service ID из консоли Apple Developer
    redirectUri: 'https://example.com/auth/callback',
    responseType: appleAuthAndroid.ResponseType.ALL,
    scope: appleAuthAndroid.Scope.ALL,
    nonce: rawNonce,
    state,
  });

  const response = await appleAuthAndroid.signIn();
  // Отправляем response.code и response.id_token на сервер
}

Для Android потребуется настроить Service ID в Apple Developer Console и указать Redirect URL. Главное правило: ссылка перенаправления должна символ в символ совпадать с тем, что вбито в консоли разработчика, никаких query-параметров.

Серверная валидация

Никогда не доверяйте клиентскому user ID на слово. Клиент получает identityToken (это подписанный JWT). На сервере вы декодируете его, проверяете подпись публичными ключами Apple и сверяете nonce.

Модуль автоматически считает SHA256-хэш от переданного nonce перед отправкой в Apple (по аналогии с тем, как это делает Firebase Auth). Учитывайте этот момент на бэкенде: сверять нужно хэшированное значение.

Если перед вами стоит задача быстро закрыть требования App Store Review или дать пользователям удобный вход в один тап через Face ID, библиотека от Invertase — самый надежный выбор в экосистеме React Native. Она избавит от написания собственного нативного моста на Swift/Objective-C, аккуратно решает вопрос со стилями кнопок и стабильно обновляется авторами. Поставил, настроил сертификаты в Apple Developer Console, прописал обработчик — и релиз готов к отправке.

🍪 Мы используем файлы cookie и сервис аналитики Яндекс.Метрика, чтобы сайт работал лучше. Продолжая пользоваться devtrends.ru, вы соглашаетесь с обработкой данных согласно Политике конфиденциальности.