Вы можете позволить своим пользователям проходить аутентификацию с помощью Firebase, используя свой Apple ID, используя Firebase SDK для выполнения сквозного потока входа OAuth 2.0.
Прежде чем вы начнете
Чтобы войти в систему пользователей с помощью Apple, сначала настройте Вход с помощью Apple на сайте разработчика Apple, а затем включите Apple в качестве поставщика входа для вашего проекта Firebase.
Присоединяйтесь к программе разработчиков Apple
Вход с помощью Apple может быть настроен только участниками программы Apple Developer Program .
Настроить вход через Apple
Apple Sign In должен быть включен и правильно настроен в вашем проекте Firebase. Конфигурация зависит от платформ Android и iOS. Пожалуйста, следуйте разделу «Настроить вход с помощью Apple» в руководствах iOS и / или Android, прежде чем продолжить.Включить Apple в качестве поставщика услуг входа
- В консоли Firebase откройте раздел Auth . На вкладке Метод входа включите поставщика Apple .
- Настройте параметры поставщика Apple Sign-in:
- Если вы развертываете свое приложение только на iOS, вы можете оставить поля Service ID, Apple Team ID, private key и key ID пустыми.
- Для поддержки на устройствах Android:
- Добавьте Firebase в свой проект Android . Обязательно зарегистрируйте подпись SHA-1 вашего приложения при настройке приложения в консоли Firebase.
- В консоли Firebase откройте раздел Auth . На вкладке Метод входа включите поставщика Apple . Укажите идентификатор службы, созданный в предыдущем разделе. Кроме того, в разделе конфигурации потока кода OAuth укажите свой Apple Team ID, а также закрытый ключ и идентификатор ключа, которые вы создали в предыдущем разделе.
Соблюдать требования Apple к анонимности данных
Вход с помощью Apple дает пользователям возможность анонимизировать свои данные, включая адрес электронной почты, при входе в систему. Пользователи, которые выбирают этот вариант, имеют адреса электронной почты с доменом privaterelay.appleid.com
. Когда вы используете Вход с Apple в своем приложении, вы должны соблюдать все применимые политики или условия Apple для разработчиков в отношении этих анонимных идентификаторов Apple ID.
Это включает в себя получение любого необходимого согласия пользователя перед тем, как связать любую прямую идентифицирующую личную информацию с анонимным идентификатором Apple ID. При использовании аутентификации Firebase это может включать в себя следующие действия:
- Свяжите адрес электронной почты с анонимным Apple ID или наоборот.
- Свяжите номер телефона с анонимным Apple ID или наоборот
- Свяжите неанонимные учетные данные соцсетей (Facebook, Google и т. Д.) С анонимным идентификатором Apple ID или наоборот.
Приведенный выше список не является исчерпывающим. См. Лицензионное соглашение программы Apple Developer в разделе «Членство» вашей учетной записи разработчика, чтобы убедиться, что ваше приложение соответствует требованиям Apple.
Доступ к классу firebase::auth::Auth
Класс Auth
- это шлюз для всех вызовов API.- Добавьте файлы заголовков Auth и App:
#include "firebase/app.h" #include "firebase/auth.h"
- В вашем коде инициализации создайте класс
firebase::App
.#if defined(__ANDROID__) firebase::App* app = firebase::App::Create(firebase::AppOptions(), my_jni_env, my_activity); #else firebase::App* app = firebase::App::Create(firebase::AppOptions()); #endif // defined(__ANDROID__)
-
firebase::auth::Auth
классfirebase::auth::Auth
для своегоfirebase::App
. МеждуApp
иAuth
однозначное соответствие.firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app);
Управляйте процессом входа с помощью Firebase SDK
Процесс входа в систему с помощью Apple зависит от платформ iOS и Android.
На iOS
Аутентифицируйте своих пользователей с помощью Firebase с помощью SDK Apple Sign In Objective-C, вызываемого из вашего кода C ++.
Для каждого запроса на вход сгенерируйте случайную строку - nonce - которую вы будете использовать, чтобы убедиться, что полученный вами идентификатор идентификатора был предоставлен специально в ответ на запрос аутентификации вашего приложения. Этот шаг важен для предотвращения атак повторного воспроизведения.
- (NSString *)randomNonce:(NSInteger)length { NSAssert(length > 0, @"Expected nonce to have positive length"); NSString *characterSet = @"0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._"; NSMutableString *result = [NSMutableString string]; NSInteger remainingLength = length; while (remainingLength > 0) { NSMutableArray *randoms = [NSMutableArray arrayWithCapacity:16]; for (NSInteger i = 0; i < 16; i++) { uint8_t random = 0; int errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random); NSAssert(errorCode == errSecSuccess, @"Unable to generate nonce: OSStatus %i", errorCode); [randoms addObject:@(random)]; } for (NSNumber *random in randoms) { if (remainingLength == 0) { break; } if (random.unsignedIntValue < characterSet.length) { unichar character = [characterSet characterAtIndex:random.unsignedIntValue]; [result appendFormat:@"%C", character]; remainingLength--; } } } }
Вы отправите SHA256-хэш одноразового номера с вашим запросом на вход, который Apple передаст в ответе без изменений. Firebase проверяет ответ, хешируя исходный одноразовый номер и сравнивая его со значением, переданным Apple.
Запустите процесс входа Apple, включая в свой запрос хэш SHA256 одноразового номера и класс делегата, который будет обрабатывать ответ Apple (см. Следующий шаг):
- (void)startSignInWithAppleFlow { NSString *nonce = [self randomNonce:32]; self.currentNonce = nonce; ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init]; ASAuthorizationAppleIDRequest *request = [appleIDProvider createRequest]; request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail]; request.nonce = [self stringBySha256HashingString:nonce]; ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]]; authorizationController.delegate = self; authorizationController.presentationContextProvider = self; [authorizationController performRequests]; } - (NSString *)stringBySha256HashingString:(NSString *)input { const char *string = [input UTF8String]; unsigned char result[CC_SHA256_DIGEST_LENGTH]; CC_SHA256(string, (CC_LONG)strlen(string), result); NSMutableString *hashed = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; for (NSInteger i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) { [hashed appendFormat:@"%02x", result[i]]; } return hashed; }
Обрабатывайте ответ Apple в своей реализации ASAuthorizationControllerDelegate`. Если вход прошел успешно, используйте токен идентификатора из ответа Apple с нехешированным одноразовым номером для аутентификации с помощью Firebase:
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) { if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) { ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential; NSString *rawNonce = self.currentNonce; NSAssert(rawNonce != nil, @"Invalid state: A login callback was received, but no login request was sent."); if (appleIDCredential.identityToken == nil) { NSLog(@"Unable to fetch identity token."); return; } NSString *idToken = [[NSString alloc] initWithData:appleIDCredential.identityToken encoding:NSUTF8StringEncoding]; if (idToken == nil) { NSLog(@"Unable to serialize id token from data: %@", appleIDCredential.identityToken); } }
Используйте полученную строку токена и оригинальный одноразовый номер, чтобы создать учетные данные Firebase и войти в Firebase.
firebase::auth::OAuthProvider::GetCredential( /*provider_id=*/"apple.com", token, nonce, /*access_token=*/nullptr); firebase::Future<firebase::auth::User*> result = auth->SignInWithCredential(credential);
Тот же шаблон можно использовать с
Reauthenticate
который можно использовать для получения новых учетных данных для конфиденциальных операций, требующих недавнего входа в систему.firebase::Future<firebase::auth::SignInResult> result = user->Reauthenticate(credential);
Тот же шаблон можно использовать для привязки учетной записи к Apple Sign In. Однако вы можете столкнуться с ошибкой, если существующая учетная запись Firebase уже связана с учетной записью Apple, с которой вы пытаетесь установить связь. Когда это произойдет, в будущем будет возвращен статус
kAuthErrorCredentialAlreadyInUse
а объект UserInfoSignInResult
может содержать действительныйupdated_credential
. Эти учетные данные можно использовать для входа в учетную запись, связанную с Apple, черезSignInWithCredential
без необходимости создания еще одного токена входа Apple и одноразового номера.Обратите внимание, что вы должны использовать
LinkAndRetrieveDataWithCredential
чтобы эта операция содержала учетные данные, посколькуupdated_credential
является членом объектаSignInResult.UserInfo
.firebase::Future<firebase::auth::SignInResult> link_result = auth->current_user()->LinkAndRetrieveDataWithCredential(credential); // To keep example simple, wait on the current thread until call completes. while (link_result.status() == firebase::kFutureStatusPending) { Wait(100); } // Determine the result of the link attempt if (link_result.error() == firebase::auth::kAuthErrorNone) { // user linked correctly. } else if (link_result.error() == firebase::auth::kAuthErrorCredentialAlreadyInUse && link_result.result()->info.updated_credential.is_valid()) { // Sign In with the new credential firebase::Future<firebase::auth::User*> result = auth->SignInWithCredential( link_result.result()->info.updated_credential); } else { // Another link error occurred. }
На Android
На Android аутентифицируйте своих пользователей с помощью Firebase, интегрировав общий веб-вход OAuth в свое приложение с помощью Firebase SDK, чтобы выполнить сквозной поток входа.
Чтобы обработать входной поток с помощью Firebase SDK, выполните следующие действия:
Создайте экземпляр
FederatedOAuthProviderData
настроенный с идентификатором поставщика, подходящим для Apple.firebase::auth::FederatedOAuthProviderData provider_data("apple.com");
Необязательно: укажите дополнительные области OAuth 2.0 помимо значений по умолчанию, которые вы хотите запросить у поставщика проверки подлинности.
provider_data.scopes.push_back("email"); provider_data.scopes.push_back("name");
Необязательно: если вы хотите отображать экран входа Apple на языке, отличном от английского, установите параметр
locale
. См. Документацию « Вход с помощью Apple» для получения информации о поддерживаемых регионах.// Localize to French. provider_data.custom_parameters["language"] = "fr"; ```
После настройки данных вашего провайдера используйте их для создания FederatedOAuthProvider.
// Construct a FederatedOAuthProvider for use in Auth methods. firebase::auth::FederatedOAuthProvider provider(provider_data);
Выполните аутентификацию с помощью Firebase, используя объект поставщика аутентификации. Обратите внимание, что в отличие от других операций FirebaseAuth, эта функция будет управлять вашим пользовательским интерфейсом, открывая веб-представление, в котором пользователь может ввести свои учетные данные.
Чтобы начать процесс входа, позвоните
signInWithProvider
:firebase::Future<firebase::auth::SignInResult> result = auth->SignInWithProvider(provider_data);
Затем ваше приложение может подождать или зарегистрировать обратный вызов в Future .
Тот же шаблон можно использовать с
ReauthenticateWithProvider
который можно использовать для получения новых учетных данных для конфиденциальных операций, требующих недавнего входа в систему.firebase::Future<firebase::auth::SignInResult> result = user->ReauthenticateWithProvider(provider_data);
Затем ваше приложение может подождать или зарегистрировать обратный вызов в Future .
Кроме того, вы можете использовать
linkWithCredential()
для привязки различных поставщиков удостоверений к существующим учетным записям.Обратите внимание, что Apple требует, чтобы вы получили явное согласие пользователей, прежде чем связывать их учетные записи Apple с другими данными.
Например, чтобы связать учетную запись Facebook с текущей учетной записью Firebase, используйте токен доступа, который вы получили при входе пользователя в Facebook:
// Initialize a Facebook credential with a Facebook access token. AuthCredential credential = firebase::auth::FacebookAuthProvider.getCredential(token); // Assuming the current user is an Apple user linking a Facebook provider. firebase::Future<firebase::auth::SignInResult> result = auth.getCurrentUser().linkWithCredential(credential);
Войти с помощью Apple Notes
В отличие от других поставщиков, поддерживаемых Firebase Auth, Apple не предоставляет URL-адрес фотографии.
Кроме того, когда пользователь решает не делиться своей электронной почтой с приложением, Apple предоставляет уникальный адрес электронной почты для этого пользователя (в форме xyz@privaterelay.appleid.com
), которым он делится с вашим приложением. Если вы настроили частную службу ретрансляции электронной почты, Apple пересылает электронные письма, отправленные на анонимный адрес, на реальный адрес электронной почты пользователя.
Apple предоставляет приложениям такую информацию, как отображаемое имя, только при первом входе в систему. Обычно Firebase сохраняет отображаемое имя при первом getCurrentUser().getDisplayName()
пользователя в Apple, что можно получить с помощью getCurrentUser().getDisplayName()
. Однако, если вы ранее использовали Apple для входа пользователя в приложение без использования Firebase, Apple не предоставит Firebase отображаемое имя пользователя.
Следующие шаги
После того, как пользователь входит в систему в первый раз, создается новая учетная запись пользователя, связанная с учетными данными, то есть с именем пользователя и паролем, номером телефона или информацией о провайдере аутентификации, с которыми пользователь вошел в систему. Эта новая учетная запись хранится как часть вашего проекта Firebase и может использоваться для идентификации пользователя в каждом приложении в вашем проекте, независимо от того, как пользователь входит в систему.В своих приложениях вы можете получить основную информацию профиля пользователя из объекта firebase :: auth :: user. См. Управление пользователями .
В своей базе данных Firebase Realtime и правилах безопасности облачного хранилища вы можете получить уникальный идентификатор пользователя вошедшего в систему из переменной auth и использовать его для управления данными, к которым пользователь может получить доступ.