Android'de Apple Kullanarak Kimlik Doğrulama

Uçtan uca OAuth 2.0 oturum açma akışını gerçekleştirmek için Firebase SDK'sını kullanarak kullanıcılarınızın Apple Kimliklerini kullanarak Firebase'de kimlik doğrulaması yapmasına izin verebilirsiniz.

Başlamadan önce

Kullanıcıların Apple ile oturum açmasını sağlamak için önce Apple'ın geliştirici sitesinde Apple ile Oturum Açma'yı yapılandırın, ardından Firebase projeniz için oturum açma sağlayıcı olarak Apple'ı etkinleştirin.

Apple Geliştirici Programı'na katılma

Apple ile oturum açma özelliği yalnızca Apple Developer Program üyeleri tarafından yapılandırılabilir.

Apple ile oturum açma özelliğini yapılandırma

Apple Developer sitesinde aşağıdakileri yapın:

  1. Web için Apple ile oturum açma özelliğini yapılandırma başlıklı makalenin ilk bölümünde açıklandığı şekilde web sitenizi uygulamanızla ilişkilendirin. İstendiğinde aşağıdaki URL'yi Dönüş URL'si olarak kaydedin:

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

    Firebase proje kimliğinizi Firebase konsol ayarları sayfasında bulabilirsiniz.

    İşlemi tamamladığınızda yeni hizmet kimliğinizi not edin. Bu kimliğe bir sonraki bölümde ihtiyacınız olacak.

  2. Apple ile oturum açma özel anahtarı oluşturun. Bir sonraki bölümde yeni özel anahtarınız ve anahtar kimliğiniz gereklidir.
  3. Kullanıcılara e-posta gönderen Firebase Authentication özelliklerinden herhangi birini kullanıyorsanız (ör. e-posta bağlantısıyla oturum açma, e-posta adresi doğrulama, hesap değişikliği iptali vb.), Apple'ın özel e-posta aktarma hizmetini yapılandırın ve noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com (veya özelleştirilmiş e-posta şablonu alanınız) için kayıt yapın. Böylece Apple, Firebase Authentication tarafından gönderilen e-postaları anonimleştirilmiş Apple e-posta adreslerine aktarabilir.

Apple'ı oturum açma sağlayıcısı olarak etkinleştirme

  1. Firebase'i Android projenize ekleyin. Uygulamanızı Firebase konsolunda ayarlarken uygulamanızın SHA-1 imzasını kaydettiğinizden emin olun.
  2. Firebase konsolunda Auth (Kimlik Doğrulama) bölümünü açın. Oturum açma yöntemi sekmesinde Apple sağlayıcısını etkinleştirin. Önceki bölümde oluşturduğunuz hizmet kimliğini belirtin. Ayrıca, OAuth kod akışı yapılandırması bölümünde Apple Ekip Kimliğinizi ve önceki bölümde oluşturduğunuz özel anahtarı ve anahtar kimliğini belirtin.

Apple'ın anonimleştirilmiş veri şartlarına uyun

Apple ile Giriş, kullanıcılara oturum açarken e-posta adresleri de dahil olmak üzere verilerini anonimleştirme seçeneği sunar. Bu seçeneği belirleyen kullanıcıların privaterelay.appleid.com alan adıyla e-posta adresleri olur. Uygulamanızda Apple ile Giriş'i kullandığınızda, bu anonimleştirilmiş Apple kimlikleriyle ilgili olarak Apple'ın geçerli tüm geliştirici politikalarına veya şartlarına uymanız gerekir.

Bu, kimliği doğrudan tanımlayan kişisel bilgileri anonimleştirilmiş bir Apple Kimliği ile ilişkilendirmeden önce gerekli kullanıcı iznini almayı içerir. Firebase Authentication kullanılırken aşağıdaki işlemler yapılabilir:

  • Anonimleştirilmiş bir Apple Kimliği'ne e-posta adresi bağlayabilir veya tam tersini yapabilirsiniz.
  • Anonimleştirilmiş bir Apple Kimliği'ne telefon numarası bağlama veya tam tersi
  • Anonim olmayan bir sosyal kimlik bilgisini (Facebook, Google vb.) anonimleştirilmiş bir Apple Kimliği'ne veya tam tersi şekilde bağlamak

Yukarıdaki listede olası her duruma yer verilmemiştir. Uygulamanızın Apple'ın şartlarını karşıladığından emin olmak için geliştirici hesabınızın Üyelik bölümündeki Apple Geliştirici Programı Lisans Sözleşmesi'ne bakın.

Firebase SDK ile oturum açma akışını yönetme

Android'de, kullanıcılarınızın Apple hesaplarını kullanarak Firebase ile kimliklerini doğrulamanın en kolay yolu, oturum açma akışının tamamını Firebase Android SDK ile yönetmektir.

Firebase Android SDK ile oturum açma akışını işlemek için aşağıdaki adımları uygulayın:

  1. Sağlayıcı kimliği apple.com ile Builder'ını kullanarak bir OAuthProvider örneği oluşturun:

    Kotlin

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

    Java

    OAuthProvider.Builder provider = OAuthProvider.newBuilder("apple.com");
    
  2. İsteğe bağlı: Kimlik doğrulama sağlayıcısından istemek istediğiniz, varsayılanın ötesindeki ek OAuth 2.0 kapsamlarını belirtin.

    Kotlin

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

    Java

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

    E-posta adresi başına bir hesap ayarı varsayılan olarak etkinleştirildiğinde Firebase, e-posta ve ad kapsamları ister. Bu ayarı Bir e-posta adresi için birden fazla hesap olarak değiştirirseniz Firebase, siz belirtmediğiniz sürece Apple'dan kapsam isteğinde bulunmaz.

  3. İsteğe bağlı: Apple'ın oturum açma ekranını İngilizce dışında bir dilde göstermek istiyorsanız locale parametresini ayarlayın. Desteklenen yerel ayarlar için Apple ile Giriş dokümanlarına bakın.

    Kotlin

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

    Java

    // Localize the Apple authentication screen in French.
    provider.addCustomParameter("locale", "fr");
    
  4. OAuth sağlayıcı nesnesini kullanarak Firebase ile kimlik doğrulayın. Diğer FirebaseAuth işlemlerinden farklı olarak bu işlemin, Özel Chrome Sekmesi açarak kullanıcı arayüzünüzü kontrol edeceğini unutmayın. Bu nedenle, OnSuccessListener ve OnFailureListener'de Etkinliğinize referans vermeyin. Bunlar, işlem kullanıcı arayüzünü başlattığında hemen ayrılır.

    Öncelikle yanıt alıp almadığınızı kontrol etmeniz gerekir. Bu yöntemle oturum açtığınızda Etkinliğiniz arka plana alınır. Bu nedenle, oturum açma akışı sırasında sistem tarafından geri alınabilir. Bu durum yaşandığında kullanıcının tekrar denemesini önlemek için sonucun zaten mevcut olup olmadığını kontrol etmeniz gerekir.

    Bekleyen sonuç olup olmadığını kontrol etmek için getPendingAuthResult() numaralı telefonu arayın:

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

    Bekleyen bir sonuç yoksa startActivityForSignInWithProvider() numaralı telefonu arayarak oturum açma akışını başlatın:

    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 tarafından desteklenen diğer sağlayıcıların aksine Apple, fotoğraf URL'si sağlamaz.

    Ayrıca, kullanıcı e-postasını uygulamayla paylaşmamayı seçtiğinde Apple, bu kullanıcı için benzersiz bir e-posta adresi (xyz@privaterelay.appleid.com biçiminde) sağlar ve bu adresi uygulamanızla paylaşır. Özel e-posta geçiş hizmetini yapılandırdıysanız Apple, anonimleştirilmiş adrese gönderilen e-postaları kullanıcının gerçek e-posta adresine yönlendirir.

    Apple, kullanıcı bilgilerini (ör. görünen ad) uygulamalarla yalnızca kullanıcı ilk kez oturum açtığında paylaşır. Firebase, genellikle kullanıcının Apple ile ilk kez oturum açtığında görünen adı depolar. Bu adı getCurrentUser().getDisplayName() ile alabilirsiniz. Ancak daha önce Firebase'i kullanmadan bir kullanıcının uygulamada oturum açması için Apple'ı kullandıysanız Apple, Firebase'e kullanıcının görünen adını sağlamaz.

Yeniden kimlik doğrulama ve hesap bağlama

Aynı kalıp, startActivityForReauthenticateWithProvider() ile de kullanılabilir. Bu kalıbı, son oturum açma işleminin gerekli olduğu hassas işlemler için yeni kimlik bilgisi almak üzere kullanabilirsiniz:

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

Ayrıca, farklı kimlik sağlayıcıları mevcut hesaplara bağlamak için linkWithCredential() kullanabilirsiniz.

Apple'ın, kullanıcıların Apple hesaplarını diğer verilere bağlamadan önce kullanıcılardan açık rıza almanızı zorunlu kıldığını unutmayın.

Örneğin, bir Facebook hesabını mevcut Firebase hesabına bağlamak için kullanıcıyı Facebook'ta oturum açtığında aldığınız erişim jetonunu kullanın:

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

Gelişmiş: Oturum açma akışını manuel olarak yönetme

Oturum açma akışını Apple ile Oturum Açma JS SDK'sını kullanarak, OAuth akışını manuel olarak oluşturarak veya AppAuth gibi bir OAuth kitaplığı kullanarak yönetip Apple Hesabı ile Firebase'de kimlik doğrulaması da yapabilirsiniz.

  1. Her oturum açma isteği için rastgele bir dize ("nonce") oluşturun. Bu dizeyi, aldığınız kimlik jetonunun özellikle uygulamanızın kimlik doğrulama isteğine yanıt olarak verildiğinden emin olmak için kullanırsınız. Bu adım, yeniden oynatma saldırılarını önlemek için önemlidir.

    Aşağıdaki örnekte olduğu gibi, Android'de SecureRandom ile kriptografik olarak güvenli bir tek kullanımlık sayı oluşturabilirsiniz:

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

    Ardından, nonce'ın SHA256 karma değerini onaltılık dize olarak alın:

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

    Oturum açma isteğinizle birlikte nonce'ın SHA256 hash değerini gönderirsiniz. Bu değer, Apple tarafından yanıtta değiştirilmeden iletilir. Firebase, orijinal nonce'ı karma oluşturma işlevinden geçirerek ve Apple tarafından iletilen değerle karşılaştırarak yanıtı doğrular.

  2. OAuth kitaplığınızı veya başka bir yöntemi kullanarak Apple'ın oturum açma akışını başlatın. Karma oluşturma işlemi uygulanmış nonce'ı isteğinize parametre olarak eklediğinizden emin olun.

  3. Apple'ın yanıtını aldıktan sonra, yanıttan kimlik jetonunu alın ve AuthCredential oluşturmak için bu jetonu ve karma oluşturulmamış nonce'u kullanın:

    Kotlin

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

    Java

    AuthCredential credential =  OAuthProvider.newCredentialBuilder("apple.com")
        .setIdTokenWithRawNonce(appleIdToken, rawUnhashedNonce)
        .build();
    
  4. Firebase kimlik bilgisiyle Firebase'de kimlik doğrulama:

    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 çağrısı başarılı olursa kullanıcının hesap verilerini almak için getCurrentUser yöntemini kullanabilirsiniz.

Jetonu İptal Etme

Apple, hesap oluşturmayı destekleyen uygulamaların, App Store İnceleme Kuralları'nda belirtildiği gibi kullanıcıların hesaplarını uygulama içinden silmelerine olanak tanımasını zorunlu kılar.

Ayrıca, Apple ile oturum açma özelliğini destekleyen uygulamalar, kullanıcı jetonlarını iptal etmek için Apple ile oturum açma REST API'sini kullanmalıdır.

Bu koşulu karşılamak için aşağıdaki adımları uygulayın:

  1. Apple ile oturum açmak ve AuthResult almak için startActivityForSignInWithProvider() yöntemini kullanın.

  2. Apple sağlayıcısı için erişim jetonunu alın.

    Kotlin

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

    Java

    OAuthCredential oauthCredential = (OAuthCredential) authResult.getCredential();
    String accessToken = oauthCredential.getAccessToken();
    
  3. revokeAccessToken API'yi kullanarak jetonu iptal edin.

    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 ...
              }
            }
      });
    
  1. Son olarak, kullanıcı hesabını (ve ilişkili tüm verileri) silin.

    Sonraki adımlar

    Bir kullanıcı ilk kez oturum açtıktan sonra yeni bir kullanıcı hesabı oluşturulur ve kullanıcının oturum açtığı kimlik bilgilerine (kullanıcı adı ve şifre, telefon numarası veya kimlik doğrulama sağlayıcı bilgileri) bağlanır. Bu yeni hesap, Firebase projenizin bir parçası olarak depolanır ve kullanıcının oturum açma şeklinden bağımsız olarak projenizdeki her uygulamada kullanıcıyı tanımlamak için kullanılabilir.

    • Uygulamalarınızda, kullanıcının temel profil bilgilerini FirebaseUser nesnesinden alabilirsiniz. Kullanıcıları yönetme başlıklı makaleyi inceleyin.

    • Firebase Realtime Database ve Cloud Storage Güvenlik Kurallarınızda, oturum açmış kullanıcının benzersiz kullanıcı kimliğini auth değişkeninden alabilir ve kullanıcının hangi verilere erişebileceğini kontrol etmek için bu kimliği kullanabilirsiniz.

    Kimlik doğrulama sağlayıcı kimlik bilgilerini mevcut bir kullanıcı hesabına bağlayarak kullanıcıların uygulamanızda birden fazla kimlik doğrulama sağlayıcı kullanarak oturum açmasına izin verebilirsiniz.

    Bir kullanıcının oturumunu kapatmak için signOut numaralı telefonu arayın:

    Kotlin

    Firebase.auth.signOut()

    Java

    FirebaseAuth.getInstance().signOut();