Uwierzytelnij się za pomocą Apple na Androidzie

Możesz pozwolić użytkownikom na uwierzytelnianie w Firebase przy użyciu ich Apple ID, korzystając z pakietu SDK Firebase do przeprowadzania kompleksowego procesu logowania OAuth 2.0.

Zanim zaczniesz

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

Dołącz do programu deweloperskiego Apple

Logowanie za pomocą konta Apple mogą konfigurować wyłącznie członkowie 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 przy użyciu konta 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 Ci potrzebny w następnej sekcji.

  2. Utwórz login przy użyciu klucza prywatnego Apple . W następnej sekcji będziesz potrzebować nowego klucza prywatnego i identyfikatora klucza.
  3. Jeśli korzystasz z którejkolwiek funkcji uwierzytelniania Firebase, która wysyła wiadomości e-mail do użytkowników, w tym logowania do łącza e-mail, weryfikacji adresu e-mail, unieważniania zmiany konta i innych, skonfiguruj usługę przekazywania prywatnych wiadomości e-mail firmy Apple i zarejestruj się noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com (lub Twoja dostosowana domena szablonu wiadomości e-mail), aby Apple mógł przekazywać e-maile wysyłane przez uwierzytelnianie Firebase na anonimowe adresy e-mail Apple.

Włącz firmę Apple jako dostawcę logowania

  1. Dodaj Firebase do swojego projektu na Androida . Pamiętaj, aby zarejestrować podpis SHA-1 swojej aplikacji podczas konfigurowania aplikacji w konsoli Firebase.
  2. W konsoli Firebase otwórz sekcję Uwierzytelnianie . 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 identyfikator zespołu Apple oraz klucz prywatny i identyfikator klucza utworzone w poprzedniej sekcji.

Spełniaj wymagania Apple dotyczące anonimowych danych

Zaloguj się przez Apple daje użytkownikom możliwość anonimizacji swoich danych, w tym adresu e-mail, podczas logowania. Użytkownicy, którzy wybiorą tę opcję, mają adresy e-mail w domenie privaterelay.appleid.com . Korzystając w aplikacji z funkcji Zaloguj się przez Apple, musisz przestrzegać wszelkich obowiązujących zasad i warunków programistycznych Apple dotyczących tych anonimowych identyfikatorów Apple ID.

Obejmuje to uzyskanie wymaganej zgody użytkownika przed powiązaniem jakichkolwiek danych osobowych bezpośrednio identyfikujących z zanonimizowanym 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 i odwrotnie.
  • Połącz numer telefonu z anonimowym identyfikatorem Apple ID i odwrotnie
  • Połącz nieanonimowe dane uwierzytelniające w mediach społecznościowych (Facebook, Google itp.) z anonimowym identyfikatorem Apple ID i odwrotnie.

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

Obsługuj proces logowania za pomocą pakietu SDK Firebase

W systemie Android najłatwiejszym sposobem uwierzytelnienia użytkowników w Firebase przy użyciu kont Apple jest obsługa całego procesu logowania za pomocą pakietu SDK Firebase dla systemu Android.

Aby obsłużyć proces logowania za pomocą pakietu SDK Firebase dla systemu Android, wykonaj następujące kroki:

  1. Skonstruuj instancję dostawcy OAuthProvider , używając 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 poza domyślnymi, których chcesz zażądać od dostawcy 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łączone jest jedno konto na adres e-mail , Firebase żąda zakresów adresu e-mail i nazw. Jeśli zmienisz to ustawienie na Wiele kont na adres e-mail , Firebase nie będzie żądać od Apple żadnych zakresów, chyba że je określisz.

  3. Opcjonalnie: Jeśli chcesz, aby ekran logowania Apple był wyświetlany w języku innym niż angielski, ustaw parametr locale . Aby zapoznać się z obsługiwanymi ustawieniami regionalnymi, zapoznaj się z dokumentacją Logowanie przy użyciu konta Apple .

    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 , ta przejmie kontrolę nad Twoim interfejsem użytkownika, otwierając niestandardową kartę Chrome. W związku z tym nie odwołuj się do swojej aktywności w dołączanych elementach OnSuccessListener i OnFailureListener , ponieważ zostaną one natychmiast odłączone po uruchomieniu operacji w interfejsie użytkownika.

    Najpierw sprawdź, czy otrzymałeś już odpowiedź. Zalogowanie się przy użyciu tej metody powoduje umieszczenie Twojej aktywności w tle, co oznacza, że ​​system może ją odzyskać podczas procesu logowania. Aby mieć pewność, że w takiej sytuacji nie zmusisz użytkownika do ponownej próby, powinieneś sprawdzić, czy wynik już się pojawił.

    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, jeśli użytkownik zdecyduje się nie udostępniać aplikacji swojego adresu e-mail, Apple przydziela temu użytkownikowi unikalny adres e-mail (w postaci xyz@privaterelay.appleid.com ), który udostępnia Twojej 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. Zwykle Firebase przechowuje nazwę wyświetlaną przy pierwszym logowaniu się użytkownika do Apple, co można uzyskać za pomocą metody getCurrentUser().getDisplayName() . Jeśli jednak wcześniej korzystałeś z usługi Apple do logowania użytkownika w aplikacji bez korzystania z Firebase, Apple nie udostępni Firebase nazwy wyświetlanej użytkownika.

Ponowne uwierzytelnienie i połączenie kont

Tego samego wzorca można użyć w przypadku startActivityForReauthenticateWithProvider() , której można użyć do pobrania nowych danych uwierzytelniających dla wrażliwych 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() , aby połączyć różnych dostawców tożsamości z istniejącymi kontami.

Pamiętaj, że 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 podczas logowania 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ęcznie obsługuj proces logowania

Możesz także uwierzytelniać się w Firebase przy użyciu konta Apple, obsługując proces logowania za pomocą pakietu 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 znaków — „nonce” — którego użyjesz, aby upewnić się, że otrzymany token identyfikacyjny został przyznany konkretnie w odpowiedzi na żądanie uwierzytelnienia Twojej aplikacji. Ten krok jest ważny, aby zapobiec atakom poprzez powtórzenie.

    Możesz wygenerować kryptograficznie bezpieczną wartość jednorazową 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 uzyskaj skrót SHA246 wartości jednorazowej 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 wartości jednorazowej, który Apple przekaże w odpowiedzi bez zmian. Firebase sprawdza odpowiedź, mieszając oryginalną wartość jednorazową i porównując ją z wartością przekazaną przez Apple.

  2. Zainicjuj proces logowania Apple przy użyciu biblioteki OAuth lub innej metody. Pamiętaj, aby w żądaniu uwzględnić zahaszowaną wartość jednorazową jako parametr.

  3. Po otrzymaniu odpowiedzi Apple pobierz z odpowiedzi token ID i użyj go oraz niezahaszowanej 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 się w Firebase przy użyciu danych uwierzytelniających 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 signInWithCredential powiedzie się, możesz użyć metody getCurrentUser , aby uzyskać dane konta użytkownika.

Cofnięcie tokena

Firma Apple wymaga, aby aplikacje obsługujące tworzenie kont umożliwiały użytkownikom zainicjowanie usunięcia konta w aplikacji, zgodnie z opisem w Wytycznych dotyczących przeglądu App Store

Ponadto aplikacje obsługujące funkcję Zaloguj się za pomocą Apple powinny używać interfejsu API REST Zaloguj się za pomocą Apple, aby unieważniać tokeny użytkownika.

Aby spełnić ten wymóg, wykonaj następujące kroki:

  1. Użyj metody startActivityForSignInWithProvider() , aby zalogować się przy użyciu Apple i uzyskać AuthResult .

  2. Uzyskaj token dostępu dla dostawcy Apple.

    Kotlin+KTX

    val oauthCredential: OAuthCredential =  authResult.credential
    val accessToken = oauthCredential.accessToken
    

    Java

    OAuthCredential oauthCredential = (OAuthCredential) authResult.getCredential();
    String accessToken = oauthCredential.getAccessToken();
    
  3. Unieważnij token za pomocą interfejsu API revokeAccessToken .

    Kotlin+KTX

    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 ...
              }
            }
      });
    
  1. Na koniec usuń konto użytkownika (i wszystkie powiązane dane)

    Następne kroki

    Gdy użytkownik zaloguje się po raz pierwszy, zostanie utworzone nowe konto użytkownika i powiązane z poświadczeniami — czyli nazwą użytkownika i hasłem, numerem telefonu lub informacjami o dostawcy uwierzytelniania — za pomocą których użytkownik się zalogował. To nowe konto jest przechowywane jako część Twojego projektu Firebase i może służyć do identyfikowania użytkownika w każdej aplikacji w Twoim projekcie, niezależnie od tego, w jaki sposób użytkownik się loguje.

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

    • W regułach bezpieczeństwa bazy danych Firebase Realtime 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 może uzyskać dostęp.

    Możesz zezwolić użytkownikom na logowanie się do 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 funkcję signOut :

    Kotlin+KTX

    Firebase.auth.signOut()

    Java

    FirebaseAuth.getInstance().signOut();