Google 致力于为黑人社区推动种族平等。查看具体举措

Аутентификация с помощью 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 проверки подлинности, что отправлять электронные письма пользователей, в том числе по электронной почте ссылки входа в, адрес электронной почты проверки, изменения счетов аннулирования, а также других, настроить частную службу электронной почты ретрансляционной компании noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com 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 с использованием своего Builder с провайдером ID 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 и 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 сохраняет отображаемое имя в первый раз , когда пользователь знаки в с 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 путем обработки входа в потоке либо с помощью Apple , Sign-In JS SDK, чтобы вручную создавать поток 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, получить идентификатор маркера из ответа и использовать его и unhashed временного значение для создания 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 Cloud Storage правил безопасности , вы можете получить подписанный в уникальном пользователя идентификатор пользователя из auth переменной и использовать его , чтобы контролировать , какие данные пользователь заходит может.

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

Чтобы выйти пользователь, вызовите signOut :

Джава

FirebaseAuth.getInstance().signOut();

Котлин + KTX

Firebase.auth.signOut()