Uwierzytelnij się za pomocą Apple na Androidzie

Możesz zezwolić użytkownikom na uwierzytelnianie w Firebase przy użyciu ich identyfikatora Apple ID przy użyciu pakietu Firebase SDK do przeprowadzania kompleksowego procesu logowania OAuth 2.0.

Zanim zaczniesz

Aby logować użytkowników za pomocą Apple, najpierw skonfiguruj opcję Logowanie się z Apple w witrynie dla programistów Apple, a następnie włącz Apple jako dostawcę logowania dla swojego projektu Firebase.

Dołącz do Programu dla programistów Apple

Logowanie się przez Apple może być skonfigurowane tylko przez członków programu Apple Developer Program .

Skonfiguruj logowanie za pomocą Apple

W witrynie Apple Developer wykonaj następujące czynności:

  1. Powiąż swoją witrynę internetową z aplikacją zgodnie z opisem w pierwszej sekcji Konfigurowanie logowania przez Apple w Internecie . Po wyświetleniu monitu zarejestruj następujący adres URL jako zwrotny adres URL:

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

    Identyfikator projektu Firebase możesz uzyskać na stronie ustawień konsoli Firebase .

    Kiedy skończysz, zanotuj swój nowy identyfikator usługi, który będzie potrzebny w następnej sekcji.

  2. Utwórz logowanie za pomocą klucza prywatnego Apple . W następnej sekcji będziesz potrzebować nowego klucza prywatnego i identyfikatora klucza.
  3. Jeśli korzystasz z funkcji uwierzytelniania Firebase, które wysyłają e-maile do użytkowników, w tym logowania za pomocą łącza e-mail, weryfikacji adresu e-mail, cofnięcia zmiany konta i innych, skonfiguruj usługę przekazywania prywatnej poczty e-mail Apple i zarejestruj noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com (lub Twoja dostosowana domena szablonu wiadomości e-mail), aby firma Apple mogła przekazywać wiadomości e-mail wysyłane przez uwierzytelnianie Firebase na anonimowe adresy e-mail firmy Apple.

Włącz Apple jako dostawcę logowania

  1. Dodaj Firebase do swojego projektu na Androida . Pamiętaj, aby zarejestrować podpis SHA-1 aplikacji podczas konfigurowania aplikacji w konsoli Firebase.
  2. W konsoli Firebase otwórz sekcję Auth . Na karcie Metoda logowania włącz dostawcę Apple . Określ identyfikator usługi utworzony w poprzedniej sekcji. Ponadto w sekcji konfiguracji przepływu kodu OAuth podaj swój Apple Team ID oraz klucz prywatny i identyfikator klucza utworzone w poprzedniej sekcji.

Przestrzegaj wymagań Apple dotyczących danych anonimowych

Funkcja Zaloguj się z Apple umożliwia użytkownikom anonimizację danych, w tym adresu e-mail, podczas logowania. Użytkownicy, którzy wybiorą tę opcję, mają adresy e-mail w domenie privaterelay.appleid.com . Gdy używasz Logowania się przez Apple w swojej aplikacji, musisz przestrzegać wszelkich obowiązujących zasad deweloperskich lub warunków Apple dotyczących tych anonimowych identyfikatorów Apple ID.

Obejmuje to uzyskanie wszelkiej wymaganej zgody użytkownika przed powiązaniem jakichkolwiek bezpośrednio identyfikujących danych osobowych z anonimowym identyfikatorem Apple ID. W przypadku korzystania z uwierzytelniania Firebase może to obejmować następujące działania:

  • Połącz adres e-mail z anonimowym identyfikatorem Apple ID lub odwrotnie.
  • Połącz numer telefonu z anonimowym identyfikatorem Apple ID lub odwrotnie
  • Połącz nieanonimowe dane uwierzytelniające z serwisów społecznościowych (Facebook, Google itp.) z anonimowym identyfikatorem Apple ID lub odwrotnie.

Powyższa lista nie jest wyczerpująca. Zapoznaj się z Umową licencyjną Apple Developer Program w sekcji Członkostwo na swoim koncie programisty, aby upewnić się, że Twoja aplikacja spełnia wymagania Apple.

Obsługuj proces logowania za pomocą Firebase SDK

Na Androidzie najłatwiejszym sposobem uwierzytelnienia użytkowników w Firebase przy użyciu ich kont Apple jest obsłużenie całego procesu logowania za pomocą Firebase Android SDK.

Aby obsłużyć proces logowania za pomocą Firebase Android SDK, wykonaj te czynności:

  1. Skonstruuj instancję OAuthProvider za pomocą jego konstruktora z identyfikatorem dostawcy apple.com :

    Kotlin+KTX

    val provider = OAuthProvider.newBuilder("apple.com")
    

    Java

    OAuthProvider.Builder provider = OAuthProvider.newBuilder("apple.com");
    
  2. Opcjonalnie: Określ dodatkowe zakresy OAuth 2.0 wykraczające poza zakres domyślny, o które chcesz poprosić dostawcę uwierzytelniania.

    Kotlin+KTX

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

    Java

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

    Domyślnie, gdy włączona jest opcja Jedno konto na adres e-mail , Firebase żąda zakresów adresów e-mail i nazw. Jeśli zmienisz to ustawienie na Wiele kont na adres e-mail , Firebase nie zażąda żadnych zakresów od Apple, chyba że je określisz.

  3. Opcjonalnie: jeśli chcesz wyświetlić ekran logowania Apple w języku innym niż angielski, ustaw parametr locale . Zapoznaj się z dokumentacją Logowanie się za pomocą Apple , aby poznać obsługiwane języki.

    Kotlin+KTX

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

    Java

    // Localize the Apple authentication screen in French.
    provider.addCustomParameter("locale", "fr");
    
  4. Uwierzytelnij się w Firebase przy użyciu obiektu dostawcy OAuth. Pamiętaj, że w przeciwieństwie do innych operacji FirebaseAuth przejmie to kontrolę nad interfejsem użytkownika, otwierając niestandardową kartę Chrome. W związku z tym nie odwołuj się do swojej aktywności w OnSuccessListener i OnFailureListener , które dołączasz, ponieważ zostaną one natychmiast odłączone, gdy operacja uruchomi interfejs użytkownika.

    Najpierw sprawdź, czy otrzymałeś już odpowiedź. Zalogowanie się przy użyciu tej metody powoduje, że Twoja aktywność działa w tle, co oznacza, że ​​może zostać odzyskana przez system podczas procesu logowania. Aby upewnić się, że użytkownik nie spróbuje ponownie, jeśli tak się stanie, powinieneś sprawdzić, czy wynik już istnieje.

    Aby sprawdzić, czy istnieje oczekujący wynik, wywołaj getPendingAuthResult() :

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

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

    Jeśli nie ma żadnych oczekujących wyników, rozpocznij proces logowania, wywołując startActivityForSignInWithProvider() :

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

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

    W przeciwieństwie do innych dostawców obsługiwanych przez Firebase Auth, Apple nie udostępnia adresu URL zdjęcia.

    Ponadto, gdy użytkownik zdecyduje się nie udostępniać aplikacji swojego adresu e-mail, firma Apple przydziela mu unikalny adres e-mail (w postaci xyz@privaterelay.appleid.com ), który udostępnia aplikacji. Jeśli skonfigurowałeś usługę przekazywania prywatnych wiadomości e-mail, Apple przekazuje wiadomości e-mail wysłane na anonimowy adres na prawdziwy adres e-mail użytkownika.

    Apple udostępnia aplikacjom informacje o użytkowniku, takie jak nazwa wyświetlana, tylko przy pierwszym logowaniu użytkownika. Zwykle Firebase przechowuje nazwę wyświetlaną przy pierwszym logowaniu użytkownika w Apple, którą można uzyskać za pomocą getCurrentUser().getDisplayName() . Jeśli jednak wcześniej używałeś Apple do logowania użytkownika w aplikacji bez korzystania z Firebase, Apple nie udostępni Firebase nazwy wyświetlanej użytkownika.

Ponowne uwierzytelnianie i łączenie kont

Tego samego wzorca można użyć z startActivityForReauthenticateWithProvider() , której można użyć do pobrania świeżych danych uwierzytelniających dla poufnych operacji wymagających niedawnego logowania:

Kotlin+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.
    })

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

Możesz także użyć linkWithCredential() do powiązania różnych dostawców tożsamości z istniejącymi kontami.

Pamiętaj, że firma Apple wymaga uzyskania wyraźnej zgody użytkowników przed połączeniem ich kont Apple z innymi danymi.

Na przykład, aby połączyć konto na Facebooku z bieżącym kontem Firebase, użyj tokena dostępu otrzymanego po zalogowaniu użytkownika na Facebooku:

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

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

Zaawansowane: ręczna obsługa przepływu logowania

Możesz również uwierzytelnić się w Firebase przy użyciu konta Apple, obsługując przepływ logowania za pomocą zestawu Apple Sign-In JS SDK, ręcznie budując przepływ OAuth lub używając biblioteki OAuth, takiej jak AppAuth .

  1. Dla każdego żądania logowania wygeneruj losowy ciąg — „nonce” — którego użyjesz, aby upewnić się, że otrzymany token identyfikatora został przyznany specjalnie w odpowiedzi na żądanie uwierzytelnienia Twojej aplikacji. Ten krok jest ważny, aby zapobiec atakom powtórkowym.

    Możesz wygenerować kryptograficznie bezpieczny identyfikator jednorazowy na Androidzie za pomocą SecureRandom , jak w poniższym przykładzie:

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

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

    Następnie pobierz skrót SHA246 nonce jako ciąg szesnastkowy:

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

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

    Wraz z żądaniem logowania wyślesz skrót SHA256 identyfikatora jednorazowego, który Apple przekaże niezmieniony w odpowiedzi. Firebase weryfikuje odpowiedź, mieszając oryginalny identyfikator jednorazowy i porównując go z wartością przekazaną przez Apple.

  2. Zainicjuj przepływ logowania Apple przy użyciu biblioteki OAuth lub innej metody. Pamiętaj, aby w swoim żądaniu podać zahaszowaną wartość jednorazową jako parametr.

  3. Po otrzymaniu odpowiedzi firmy Apple pobierz token identyfikatora z odpowiedzi i użyj go oraz niezaszyfrowanej wartości jednorazowej, aby utworzyć AuthCredential :

    Kotlin+KTX

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

    Java

    AuthCredential credential =  OAuthProvider.newCredentialBuilder("apple.com")
        .setIdTokenWithRawNonce(appleIdToken, rawUnhashedNonce)
        .build();
    
  4. Uwierzytelnij w Firebase przy użyciu poświadczeń Firebase:

    Kotlin+KTX

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

Jeśli wywołanie funkcji signInWithCredential powiedzie się, możesz użyć metody getCurrentUser , aby uzyskać dane konta użytkownika.

Następne kroki

Gdy użytkownik zaloguje się po raz pierwszy, tworzone jest nowe konto użytkownika, które jest łączone z poświadczeniami — czyli nazwą użytkownika i hasłem, numerem telefonu lub informacjami o dostawcy autoryzacji — za pomocą których użytkownik się logował. To nowe konto jest przechowywane jako część Twojego projektu Firebase i może służyć do identyfikacji użytkownika w każdej aplikacji w Twoim projekcie, niezależnie od tego, jak użytkownik się loguje.

  • W swoich aplikacjach możesz uzyskać podstawowe informacje o profilu użytkownika z obiektu FirebaseUser . Zobacz Zarządzanie użytkownikami .

  • W regułach bezpieczeństwa Firebase Realtime Database i Cloud Storage możesz uzyskać unikalny identyfikator zalogowanego użytkownika ze zmiennej auth i użyć go do kontrolowania, do jakich danych użytkownik ma dostęp.

Możesz zezwolić użytkownikom na logowanie się do Twojej aplikacji przy użyciu wielu dostawców uwierzytelniania, łącząc poświadczenia dostawcy uwierzytelniania z istniejącym kontem użytkownika.

Aby wylogować użytkownika, wywołaj signOut :

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();