Вы можете разрешить пользователям аутентифицироваться в Firebase, используя свой Apple ID, с помощью Firebase SDK, который обеспечивает сквозной процесс авторизации OAuth 2.0.
Прежде чем начать
Для авторизации пользователей с помощью Apple сначала настройте функцию «Вход с помощью Apple» на сайте разработчиков Apple, а затем включите Apple в качестве поставщика авторизации для вашего проекта Firebase.
Присоединяйтесь к программе для разработчиков Apple!
Настроить функцию «Вход с помощью Apple» могут только участники программы Apple Developer Program .
Настройка входа в систему с помощью Apple
На сайте Apple Developer выполните следующие действия:
Свяжите свой веб-сайт с приложением, как описано в первом разделе раздела «Настройка входа в систему Apple для веб-браузера» . При появлении запроса зарегистрируйте следующий URL-адрес в качестве URL-адреса возврата:
https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
Идентификатор вашего проекта Firebase можно найти в
> Вкладка «Общие» в консоли Firebase . После завершения запишите свой новый идентификатор службы (Service ID), который понадобится вам в следующем разделе. Создайте закрытый ключ для входа в систему с помощью Apple . В следующем разделе вам понадобятся ваш новый закрытый ключ и идентификатор ключа. Если вы используете какие-либо функции Firebase Authentication , отправляющие электронные письма пользователям, включая вход по ссылке из электронной почты, подтверждение адреса электронной почты, аннулирование изменений учетной записи и другие, настройте частную службу ретрансляции электронной почты Apple и зарегистрируйте noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com(или домен вашего пользовательского шаблона электронной почты), чтобы Apple могла пересылать электронные письма, отправленные Firebase Authentication на анонимизированные адреса электронной почты Apple.
Включите Apple в качестве поставщика услуг авторизации.
Добавьте Firebase в свой Android-проект . Укажите SHA-1-отпечаток вашего приложения, если вы еще этого не сделали. В консоли Firebase перейдите в... > Вкладка «Общие» . Прокрутите вниз до карточки «Ваши приложения» , выберите свое приложение для Android и добавьте о��печаток SHA-1 в поле «Отпечатки сертификатов SHA» .
В консоли Firebase перейдите в раздел Безопасность > Аутентификация . На вкладке «Метод входа» включите поставщика авторизации Apple . Укажите идентификатор службы, созданный вами в предыдущем разделе. Также в разделе конфигурации потока кода OAuth укажите свой идентификатор команды Apple, а также закрытый ключ и идентификатор ключа, созданные вами в предыдущем разделе.
Соблюдайте требования Apple к анонимизации данных.
privaterelay.appleid.com . При использовании функции «Вход с Apple» в вашем приложении необходимо соблюдать все применимые правила и условия Apple для разработчиков, касающиеся этих анонимизированных Apple ID.
Привяжите адрес электронной почты к анонимизированному Apple ID или наоборот. Привязать номер телефона к анонимизированному Apple ID или наоборот. Привяжите неанонимные учетные данные из социальной сети (Facebook, Google и т. д.) к анонимизированному Apple ID или наоборот.
Обрабатывайте процесс авторизации с помощью Firebase SDK.
Создайте экземпляр OAuthProvider, используя его Builder с идентификатором поставщикаapple.com:Kotlin
val provider = OAuthProvider.newBuilder("apple.com")Java
OAuthProvider.Builder provider = OAuthProvider.newBuilder("apple.com");Необязательно: укажите дополнительные области действия OAuth 2.0, помимо области по умолчанию, которые вы хотите запросить у поставщика аутентификации. Kotlin
provider.setScopes(arrayOf("email", "name"))Java
List<String> scopes = new ArrayList<String>() { { add("email"); add("name"); } }; provider.setScopes(scopes);По умолчанию, если включена опция «Одна учетная запись на один адрес электронной почты» , Firebase запрашивает области действия для электронной почты и имени. Если вы измените этот параметр на «Несколько учетных записей на один адрес электронной почты» , Firebase не будет запрашивать у Apple никаких областей действия, если вы их не укажете. Необязательно: если вы хотите отображать экран входа в систему Apple на языке, отличном от английского, задайте параметр locale. Список поддерживаемых языковых версий см . в документации по входу в систему с помощью Apple .Kotlin
// Localize the Apple authentication screen in French. provider.addCustomParameter("locale", "fr")Java
// Localize the Apple authentication screen in French. provider.addCustomParameter("locale", "fr");Аутентификация в Firebase осуществляется с помощью объекта поставщика OAuth. Обратите внимание, что в отличие от других операций FirebaseAuth, эта операция возьмет на себя управление вашим пользовательским интерфейсом, открыв пользовательскую вкладку Chrome. Следовательно, не ссылайтесь на вашу Activity в методахOnSuccessListenerиOnFailureListener, которые вы подключаете, поскольку они немедленно отключатся, как только операция запустит пользовательский интерфейс.Сначала следует проверить, получили ли вы уже ответ. Вход в систему этим методом переводит вашу активность в фоновый режим, что означает, что система может использовать её повторно во время процесса входа. Чтобы пользователю не приходилось повторять попытку в этом случае, следует проверить, есть ли уже полученный результат. Чтобы проверить наличие ожидающих результатов, вызовите метод getPendingAuthResult():Kotlin
val pending = auth.pendingAuthResult if (pending != null) { pending.addOnSuccessListener { authResult -> Log.d(TAG, "checkPending:onSuccess:$authResult") // Get the user profile with authResult.getUser() and // authResult.getAdditionalUserInfo(), and the ID // token from Apple with authResult.getCredential(). }.addOnFailureListener { e -> Log.w(TAG, "checkPending:onFailure", e) } } else { Log.d(TAG, "pending: null") }Java
mAuth = FirebaseAuth.getInstance(); Task<AuthResult> pending = mAuth.getPendingAuthResult(); if (pending != null) { pending.addOnSuccessListener(new OnSuccessListener<AuthResult>() { @Override public void onSuccess(AuthResult authResult) { Log.d(TAG, "checkPending:onSuccess:" + authResult); // Get the user profile with authResult.getUser() and // authResult.getAdditionalUserInfo(), and the ID // token from Apple with authResult.getCredential(). } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Log.w(TAG, "checkPending:onFailure", e); } }); } else { Log.d(TAG, "pending: null"); }Если нет ожидающих результатов, запустите процесс входа в систему, вызвав startActivityForSignInWithProvider():Kotlin
auth.startActivityForSignInWithProvider(this, provider.build()) .addOnSuccessListener { authResult -> // Sign-in successful! Log.d(TAG, "activitySignIn:onSuccess:${authResult.user}") val user = authResult.user // ... } .addOnFailureListener { e -> Log.w(TAG, "activitySignIn:onFailure", e) }Java
mAuth.startActivityForSignInWithProvider(this, provider.build()) .addOnSuccessListener( new OnSuccessListener<AuthResult>() { @Override public void onSuccess(AuthResult authResult) { // Sign-in successful! Log.d(TAG, "activitySignIn:onSuccess:" + authResult.getUser()); FirebaseUser user = authResult.getUser(); // ... } }) .addOnFailureListener( new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Log.w(TAG, "activitySignIn:onFailure", e); } });В отличие от других провайдеров, поддерживаемых Firebase Auth, Apple не предоставляет URL-адрес фотографии. Кроме того, если пользователь решает не делиться своим адресом электронной почты с приложением, Apple создает для этого пользователя уникальный адрес электронной почты (в формате xyz@privaterelay.appleid.com), который затем передается вашему приложению. Если вы настроили службу пересылки частной электронной почты, Apple пересылает электронные письма, отправленные на анонимизированный адрес, на реальный адрес электронной почты пользователя.Apple передает информацию о пользователе, такую как отображаемое имя, приложениям только при первом входе пользователя в систему. Обычно Firebase сохраняет отображаемое имя при первом входе пользователя в систему Apple, и его можно получить с помощью getCurrentUser().getDisplayName(). Однако, если вы ранее использовали Apple для входа пользователя в приложение без Firebase, Apple не предоставит Firebase отображаемое имя пользователя.
Повторная аутентификация и привязка учетных записей
startActivityForReauthenticateWithProvider() , которая позволяет получить новые учетные данные для выполнения конфиденциальных операций, требующих недавнего входа в систему:
Kotlin
// The user is already signed-in.
val firebaseUser = auth.getCurrentUser()
firebaseUser
.startActivityForReauthenticateWithProvider(/* activity= */ this, provider.build())
.addOnSuccessListener( authResult -> {
// User is re-authenticated with fresh tokens and
// should be able to perform sensitive operations
// like account deletion and email or password
// update.
})
.addOnFailureListener( e -> {
// Handle failure.
})
Java
// The user is already signed-in.
FirebaseUser firebaseUser = mAuth.getCurrentUser();
firebaseUser
.startActivityForReauthenticateWithProvider(/* activity= */ this, provider.build())
.addOnSuccessListener(
new OnSuccessListener<AuthResult>() {
@Override
public void onSuccess(AuthResult authResult) {
// User is re-authenticated with fresh tokens and
// should be able to perform sensitive operations
// like account deletion and email or password
// update.
}
})
.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// Handle failure.
}
});
linkWithCredential() для привязки различных поставщиков удостоверений к существующим учетным записям.
Kotlin
// Initialize a Facebook credential with a Facebook access token.
val credential = FacebookAuthProvider.getCredential(token.getToken())
// Assuming the current user is an Apple user linking a Facebook provider.
mAuth.getCurrentUser().linkWithCredential(credential)
.addOnCompleteListener(this, task -> {
if (task.isSuccessful()) {
// Facebook credential is linked to the current Apple user.
// The user can now sign in to the same account
// with either Apple or Facebook.
}
});
Java
// Initialize a Facebook credential with a Facebook access token.
AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
// Assuming the current user is an Apple user linking a Facebook provider.
mAuth.getCurrentUser().linkWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Facebook credential is linked to the current Apple user.
// The user can now sign in to the same account
// with either Apple or Facebook.
}
}
});
Расширенные настройки: Обработка процесса входа в систему вручную
Для каждого запроса на вход в систему генерируйте случайную строку — «nonce», — которую вы будете использовать, чтобы убедиться, что полученный вами токен идентификации был предоставлен именно в ответ на запрос аутентификации вашего приложения. Этот шаг важен для предотвращения атак повторного воспроизведения. С помощью SecureRandomна Android можно сгенерировать криптографически защищенный одноразовый код (nonce), как показано в следующем примере:Kotlin
private fun generateNonce(length: Int): String { val generator = SecureRandom() val charsetDecoder = StandardCharsets.US_ASCII.newDecoder() charsetDecoder.onUnmappableCharacter(CodingErrorAction.IGNORE) charsetDecoder.onMalformedInput(CodingErrorAction.IGNORE) val bytes = ByteArray(length) val inBuffer = ByteBuffer.wrap(bytes) val outBuffer = CharBuffer.allocate(length) while (outBuffer.hasRemaining()) { generator.nextBytes(bytes) inBuffer.rewind() charsetDecoder.reset() charsetDecoder.decode(inBuffer, outBuffer, false) } outBuffer.flip() return outBuffer.toString() }Java
private String generateNonce(int length) { SecureRandom generator = new SecureRandom(); CharsetDecoder charsetDecoder = StandardCharsets.US_ASCII.newDecoder(); charsetDecoder.onUnmappableCharacter(CodingErrorAction.IGNORE); charsetDecoder.onMalformedInput(CodingErrorAction.IGNORE); byte[] bytes = new byte[length]; ByteBuffer inBuffer = ByteBuffer.wrap(bytes); CharBuffer outBuffer = CharBuffer.allocate(length); while (outBuffer.hasRemaining()) { generator.nextBytes(bytes); inBuffer.rewind(); charsetDecoder.reset(); charsetDecoder.decode(inBuffer, outBuffer, false); } outBuffer.flip(); return outBuffer.toString(); }Затем получите хеш SHA246 от полученного nonce в виде шестнадцатеричной строки: Kotlin
private fun sha256(s: String): String { val md = MessageDigest.getInstance("SHA-256") val digest = md.digest(s.toByteArray()) val hash = StringBuilder() for (c in digest) { hash.append(String.format("%02x", c)) } return hash.toString() }Java
private String sha256(String s) throws NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] digest = md.digest(s.getBytes()); StringBuilder hash = new StringBuilder(); for (byte c: digest) { hash.append(String.format("%02x", c)); } return hash.toString(); }Вместе с запросом на вход в систему вы отправите хеш SHA256 одноразового числа (nonce), который Apple передаст в ответе без изменений. Firebase проверяет ответ, хешируя исходное значение nonce и сравнивая его со значением, переданным Apple. Инициируйте процесс авторизации Apple, используя свою библиотеку OAuth или другой метод. Обяза��ельно укажите хешированный nonce в качестве параметра в вашем запросе. После получения ответа от Apple, извлеките из ответа токен ID и используйте его вместе с нехешированным nonce для создания объекта AuthCredential:Kotlin
val credential = OAuthProvider.newCredentialBuilder("apple.com") .setIdTokenWithRawNonce(appleIdToken, rawUnhashedNonce) .build()Java
AuthCredential credential = OAuthProvider.newCredentialBuilder("apple.com") .setIdTokenWithRawNonce(appleIdToken, rawUnhashedNonce) .build();Аутентификация в Firebase с использованием учетных данных Firebase: Kotlin
auth.signInWithCredential(credential) .addOnCompleteListener(this) { task -> if (task.isSuccessful) { // User successfully signed in with Apple ID token. // ... } }Java
mAuth.signInWithCredential(credential) .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isSuccessful()) { // User successfully signed in with Apple ID token. // ... } } });
signInWithCredential пройден успешно, вы можете использовать метод getCurrentUser для получения данных учетной записи пользователя.
Отзыв токена
Используйте метод startActivityForSignInWithProvider()для входа в систему с помощью Apple и полученияAuthResult.Получите токен доступа для поставщика услуг Apple. Kotlin
val oauthCredential: OAuthCredential = authResult.credential val accessToken = oauthCredential.accessTokenJava
OAuthCredential oauthCredential = (OAuthCredential) authResult.getCredential(); String accessToken = oauthCredential.getAccessToken();Отзовите токен, используя API revokeAccessToken.Kotlin
mAuth.revokeAccessToken(accessToken) .addOnCompleteListener(this) { task -> if (task.isSuccessful) { // Access token successfully revoked // for the user ... } }Java
mAuth.revokeAccessToken(accessToken) .addOnCompleteListener(this, new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { // Access token successfully revoked // for the user ... } } });
Наконец, удалите учетную запись пользователя (и все связанные с ней данные). Следующие шаги
После первого входа пользователя в систему создается новая учетная запись, которая связывается с учетными данными — то есть именем пользователя и паролем, номером телефона или информацией о поставщике аутентификации, — которые пользователь использовал для входа. Эта новая учетная запись хранится как часть вашего проекта Firebase и может использоваться для идентификации пользователя во всех приложениях вашего проекта, независимо от способа входа пользователя.
�� ваших приложениях вы можете получить основную информацию профиля пользователя из объекта
FirebaseUser. См. раздел «Управление пользователями» .В правилах безопасности Firebase Realtime Database и Cloud Storage вы можете получить уникальный идентификатор пользователя, вошедшего в систему, из переменной
authи использовать его для управления доступом пользователя к данным.
Вы можете разрешить пользователям входить в ваше приложение, используя несколько поставщиков аутентификации, связав учетные данные поставщика аутентификации с существующей учетной записью пользователя.
Для выхода из системы пользователя вызовите
signOut:Kotlin
Firebase.auth.signOut()
Java
FirebaseAuth.getInstance().signOut();