Разработка авторизации через Apple ID (Sign in with Apple)
С 2019 года Apple обязала: если в iOS-приложении есть авторизация через сторонние identity-провайдеры (Google, Facebook, VK), — Sign in with Apple обязан быть. Rejection по 4.8.0 в App Store Review — частая история у команд, которые интегрировали Google Sign-In, но проигнорировали Apple. Это не просто требование ревью — это хорошая авторизация с privacy-центричным дизайном.
Что делает Sign in with Apple особенным
Apple не отдаёт реальный email пользователя приложению — если пользователь выбрал скрытие email, приложение получает relay-адрес вида [email protected]. Письма на этот адрес Apple пересылает на реальный. Если пользователь отзывает доступ приложению — relay перестаёт работать.
Имя и email передаются только один раз — при первой авторизации. Если вы не сохранили их в своей базе — при повторном входе Apple их не отдаст. Это не баг, это намеренное решение Apple. Команды, которые не знали об этом, обнаруживали проблему в продакшене: пользователи не могут повторно войти потому что backend не сохранил email при первой авторизации.
Реализация на iOS
import AuthenticationServices
// Запрос авторизации
let appleIDProvider = ASAuthorizationAppleIDProvider()
let request = appleIDProvider.createRequest()
request.requestedScopes = [.fullName, .email]
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
authorizationController.delegate = self
authorizationController.presentationContextProvider = self
authorizationController.performRequests()
// Обработка результата
func authorizationController(controller: ASAuthorizationController,
didCompleteWithAuthorization authorization: ASAuthorization) {
guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential else { return }
let userID = credential.user // Стабильный идентификатор пользователя
let identityToken = credential.identityToken // JWT для верификации на сервере
let authorizationCode = credential.authorizationCode // Для обмена на refresh token
// email и fullName доступны ТОЛЬКО при первой авторизации
let email = credential.email
let fullName = credential.fullName
}
credential.user — стабильный идентификатор, уникальный для пары (пользователь, приложение). Не используется для идентификации пользователя между приложениями одной команды (для этого — identityToken с sub claim).
Верификация на сервере
Клиент передаёт identityToken (JWT) на backend. Сервер верифицирует:
- Подпись токена публичным ключом Apple (ключи по
https://appleid.apple.com/auth/keys) -
audclaim совпадает с Bundle ID приложения -
iss=https://appleid.apple.com -
expне истёк
После первой авторизации authorizationCode обменивается на refresh_token через Apple's token endpoint. refresh_token хранится на сервере и используется для проверки, не отозвал ли пользователь доступ приложению.
Проверка статуса авторизации при каждом запуске приложения:
let appleIDProvider = ASAuthorizationAppleIDProvider()
appleIDProvider.getCredentialState(forUserID: savedUserID) { state, error in
switch state {
case .authorized: break // Всё хорошо
case .revoked: // Пользователь отозвал доступ — разлогиниваем
case .notFound: // Первый вход или данные удалены
}
}
Интеграция на Android и Web
Apple требует поддержки Sign in with Apple на всех платформах, где есть приложение. На Android — через OIDC flow в браузере (нет нативного SDK): открываем ASWebAuthenticationSession аналог через Custom Tab, авторизация через Apple's OAuth endpoint, получаем code в redirect URI.
Retrofit / OkHttp на Android: обычный OAuth2 PKCE flow с Apple's authorization endpoint. Apple не предоставляет Android SDK — только веб-браузерный flow.
Типичные ошибки
- Не сохранили email при первой авторизации — при попытке «восстановить аккаунт» пользователь не может, потому что email неизвестен
- Не реализовали проверку revocation — пользователь отозвал доступ, но в приложении остаётся залогиненным
- Не настроили Service ID для веб/Android flow —
invalid_clientошибка при OAuth2
Сроки: от 1 до 2 недель. Включает нативную iOS реализацию, серверную верификацию JWT, хранение relay email, проверку статуса при запуске, опционально — Android OAuth2 flow.







