Save the date - Google I/O returns May 18-20. Register to get the most out of the digital experience: Build your schedule, reserve space, participate in Q&As, earn Google Developer profile badges, and more. Register now
Эта страница переведена с помощью Cloud Translation API.
Switch to English

Аутентификация с помощью Apple на Android

Вы можете позволить своим пользователям проходить аутентификацию с помощью Firebase с помощью своего Apple ID, используя Firebase SDK для выполнения сквозного потока входа OAuth 2.0.

Прежде чем вы начнете

Чтобы войти в систему пользователей с помощью Apple, сначала настройте Вход с помощью Apple на сайте разработчика Apple, а затем включите Apple в качестве поставщика входа для вашего проекта Firebase.

Присоединяйтесь к программе разработчиков Apple

Вход с помощью Apple может быть настроен только участниками программы Apple Developer Program .

Настроить вход через Apple

На сайте разработчиков Apple выполните следующие действия:

  1. Свяжите свой веб-сайт с приложением, как описано в первом разделе « Настройка входа в Apple для Интернета» . При появлении запроса зарегистрируйте следующий URL-адрес в качестве URL-адреса возврата:

    https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler

    Вы можете получить свой идентификатор проекта Firebase на странице настроек консоли Firebase .

    Когда вы закончите, запишите свой новый идентификатор службы, который вам понадобится в следующем разделе.

  2. Создайте вход с закрытым ключом Apple . В следующем разделе вам понадобятся ваш новый закрытый ключ и идентификатор ключа.
  3. Если вы используете какие-либо функции Firebase Authentication, которые отправляют электронные письма пользователям, включая вход по электронной почте, подтверждение адреса электронной почты, отзыв изменения учетной записи и другие, настройте службу ретрансляции частной электронной почты Apple и зарегистрируйте noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com (или домен вашего настроенного шаблона электронной почты), чтобы Apple могла ретранслировать электронные письма, отправленные с помощью Firebase Authentication, на анонимные адреса электронной почты Apple.

Включить Apple в качестве поставщика услуг входа

  1. Добавьте Firebase в свой проект Android . Обязательно зарегистрируйте подпись SHA-1 вашего приложения при настройке приложения в консоли Firebase.
  2. В консоли 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 SDK

На Android самый простой способ аутентифицировать своих пользователей с помощью Firebase с использованием их учетных записей Apple - это обработать весь процесс входа с помощью Firebase Android SDK.

Чтобы обработать входной поток с помощью Firebase Android SDK, выполните следующие действия:

  1. OAuthProvider экземпляр OAuthProvider используя его Builder с идентификатором поставщика apple.com :

    Ява

    OAuthProvider.Builder provider = OAuthProvider.newBuilder("apple.com");
    

    Котлин + KTX

    val provider = OAuthProvider.newBuilder("apple.com")
    
  2. Необязательно: укажите дополнительные области OAuth 2.0 помимо значений по умолчанию, которые вы хотите запросить у поставщика проверки подлинности.

    Ява

    List<String> scopes =
        new ArrayList<String>() {
          {
            add("email");
            add("name");
          }
        };
    provider.setScopes(scopes);
    

    Котлин + KTX

    provider.setScopes(arrayOf("email", "name"))
    

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

  3. Необязательно: если вы хотите отображать экран входа Apple на языке, отличном от английского, установите параметр locale . См. Документацию по входу с помощью Apple, чтобы узнать о поддерживаемых региональных стандартах.

    Ява

    // Localize the Apple authentication screen in French.
    provider.addCustomParameter("locale", "fr");
    

    Котлин + KTX

    // Localize the Apple authentication screen in French.
    provider.addCustomParameter("locale", "fr")
    
  4. Выполните аутентификацию с помощью Firebase с помощью объекта поставщика OAuth. Обратите внимание, что, в отличие от других операций FirebaseAuth , он будет управлять вашим пользовательским интерфейсом, открыв настраиваемую вкладку Chrome. Следовательно, не OnSuccessListener свою Activity в OnSuccessListener и OnFailureListener которые вы присоединяете, поскольку они немедленно отключаются, когда операция запускает пользовательский интерфейс.

    Вы должны сначала проверить, получили ли вы уже ответ. При входе в систему с помощью этого метода ваша Activity находится в фоновом режиме, что означает, что она может быть восстановлена ​​системой во время процесса входа. Чтобы убедиться, что вы не заставляете пользователя повторять попытку, если это произойдет, вы должны проверить, присутствует ли уже результат.

    Чтобы проверить, есть ли ожидающий результат, вызовите getPendingAuthResult() :

    Ява

    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");
    }
    

    Котлин + KTX

    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")
    }
    

    Если ожидающих результатов нет, запустите процесс входа, вызвав startActivityForSignInWithProvider() :

    Ява

    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);
                        }
                    });
    

    Котлин + KTX

    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)
            }
    

    В отличие от других поставщиков, поддерживаемых Firebase Auth, Apple не предоставляет URL-адрес фотографии.

    Кроме того, когда пользователь решает не делиться своим адресом электронной почты с приложением, Apple предоставляет уникальный адрес электронной почты для этого пользователя (в форме xyz@privaterelay.appleid.com ), которым он делится с вашим приложением. Если вы настроили частную службу ретрансляции электронной почты, Apple пересылает электронные письма, отправленные на анонимный адрес, на реальный адрес электронной почты пользователя.

    Apple предоставляет приложениям такую ​​информацию, как отображаемое имя, только при первом входе в систему. Обычно Firebase сохраняет отображаемое имя при первом getCurrentUser().getDisplayName() пользователя в систему Apple, что можно получить с помощью getCurrentUser().getDisplayName() . Однако, если вы ранее использовали Apple для входа пользователя в приложение без использования Firebase, Apple не предоставит Firebase отображаемое имя пользователя.

Повторная аутентификация и привязка аккаунта

Тот же шаблон можно использовать с startActivityForReauthenticateWithProvider() который можно использовать для получения новых учетных данных для конфиденциальных операций, требующих недавнего входа в систему:

Ява

// 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.
          }
        });

Котлин + KTX

// 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.
    })

Кроме того, вы можете использовать linkWithCredential() для привязки различных поставщиков удостоверений к существующим учетным записям.

Обратите внимание, что Apple требует, чтобы вы получили явное согласие пользователей, прежде чем связывать их учетные записи Apple с другими данными.

Например, чтобы связать учетную запись Facebook с текущей учетной записью Firebase, используйте токен доступа, который вы получили при входе пользователя в Facebook:

Ява

// 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.
        }
      }
    });

Котлин + KTX

// 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.
        }
      });

Дополнительно: управление процессом входа вручную

Вы также можете аутентифицироваться с помощью Firebase с помощью учетной записи Apple, обрабатывая поток входа в систему с помощью JS SDK для входа в систему Apple, вручную создавая поток OAuth или используя библиотеку OAuth, такую ​​как AppAuth .

  1. Для каждого запроса на вход сгенерируйте случайную строку - nonce - которую вы будете использовать, чтобы убедиться, что полученный вами идентификатор идентификатора был предоставлен специально в ответ на запрос аутентификации вашего приложения. Этот шаг важен для предотвращения атак повторного воспроизведения.

    Вы можете сгенерировать криптографически безопасный одноразовый номер на Android с помощью SecureRandom , как в следующем примере:

    Ява

    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();
    }
    

    Котлин + KTX

    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()
    }
    

    Затем получите хэш SHA246 одноразового номера в виде шестнадцатеричной строки:

    Ява

    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();
    }
    

    Котлин + KTX

    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()
    }
    

    Вы отправите SHA256-хэш одноразового номера с вашим запросом на вход, который Apple передаст в ответе без изменений. Firebase проверяет ответ, хешируя исходный одноразовый номер и сравнивая его со значением, переданным Apple.

  2. Инициируйте процесс входа в Apple с помощью библиотеки OAuth или другим способом. Обязательно включите хешированный одноразовый номер в качестве параметра в свой запрос.

  3. После того, как вы получите ответ Apple, получите токен идентификатора из ответа и используйте его и нехешированный одноразовый номер для создания AuthCredential :

    Ява

    AuthCredential credential =  OAuthProvider.newCredentialBuilder("apple.com")
        .setIdTokenWithRawNonce(appleIdToken, rawUnhashedNonce)
        .build();
    

    Котлин + KTX

    val credential =  OAuthProvider.newCredentialBuilder("apple.com")
        .setIdTokenWithRawNonce(appleIdToken, rawUnhashedNonce)
        .build()
    
  4. Выполните аутентификацию в Firebase, используя учетные данные Firebase:

    Ява

    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.
              // ...
            }
          }
        });
    

    Котлин + KTX

    auth.signInWithCredential(credential)
          .addOnCompleteListener(this) { task ->
              if (task.isSuccessful) {
                // User successfully signed in with Apple ID token.
                // ...
              }
          }
    

Если вызов signInWithCredential успешно, вы можете использовать метод getCurrentUser для получения данных учетной записи пользователя.

Следующие шаги

После того, как пользователь входит в систему в первый раз, создается новая учетная запись пользователя, связанная с учетными данными, то есть с именем пользователя и паролем, номером телефона или информацией о провайдере аутентификации, с которыми пользователь вошел в систему. Эта новая учетная запись хранится как часть вашего проекта Firebase и может использоваться для идентификации пользователя в каждом приложении в вашем проекте, независимо от того, как пользователь входит в систему.

  • В своих приложениях вы можете получить основную информацию профиля пользователя из объекта FirebaseUser . См. Управление пользователями .

  • В своей базе данных Firebase Realtime и правилах безопасности облачного хранилища вы можете получить уникальный идентификатор пользователя вошедшего в систему из переменной auth и использовать его для управления данными, к которым пользователь может получить доступ.

Вы можете разрешить пользователям входить в ваше приложение с помощью нескольких поставщиков аутентификации, связав учетные данные поставщика аутентификации с существующей учетной записью пользователя.

Чтобы выйти из системы, вызовите signOut :

Ява

FirebaseAuth.getInstance().signOut();

Котлин + KTX

Firebase.auth.signOut()