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 ile kimlik doğrulamasına izin verebilirsiniz.

Başlamadan önce

Apple'ı kullanarak kullanıcıların oturumunu açmak için önce Apple'ın geliştirici sitesinde Apple ile Oturum Açma özelliğini yapılandırın, ardından Apple'ı Firebase projeniz için oturum açma sağlayıcısı olarak etkinleştirin.

Apple Developer Program'a katılma

Apple ile oturum açma özelliği yalnızca Apple Developer Programı'nın ü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 konsolu ayarlar sayfasından edinebilirsiniz.

    İş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ç özel anahtarı oluşturun. Bir sonraki bölümde yeni özel anahtarınızı ve anahtar kimliğinizi kullanmanız gerekir.
  3. E-posta bağlantısı ile oturum açma, e-posta adresi doğrulama, hesap değişikliği iptal etme ve diğerleri dahil olmak üzere Firebase Authentication'ın kullanıcılara e-posta gönderen özelliklerinden herhangi birini kullanıyorsanız Apple özel e-posta geçiş hizmetini yapılandırın ve Apple'ın Firebase Authentication tarafından gönderilen e-postaları anonimleştirilmiş Apple e-posta adreslerine iletebilmesi için noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com (veya özelleştirilmiş e-posta şablonu alanınızı) kaydedin.

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 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, önceki bölümde oluşturduğunuz özel anahtarı ve anahtar kimliğini belirtin.

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

Apple ile oturum açma özelliği, 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 e-posta adresleri privaterelay.appleid.com alan adıyla başlar. Uygulamanızda Apple ile oturum açma özelliğini kullandığınızda, bu anonimleştirilmiş Apple kimlikleriyle ilgili Apple'ın geçerli geliştirici politikalarına veya şartlarına uymanız gerekir.

Buna, doğrudan kimliği tanımlayan kişisel bilgileri anonimleştirilmiş bir Apple kimliğiyle ilişkilendirmeden önce gerekli kullanıcı rızasını almak da dahildir. Firebase Authentication kullanılırken bu işlemler aşağıdakileri içerebilir:

  • Bir e-posta adresini anonimleştirilmiş bir Apple Kimliği'ne veya anonimleştirilmiş bir Apple Kimliği'ni bir e-posta adresine bağlayabilirsiniz.
  • Telefon numarasını anonimleştirilmiş bir Apple Kimliği'ne veya anonimleştirilmiş Apple Kimliği'ni telefon numarasına bağlama
  • Anonim olmayan bir sosyal kimlik bilgisini (Facebook, Google vb.) anonimleştirilmiş bir Apple kimliğine veya tam tersini bağlama

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.

Oturum açma akışını Firebase SDK'sıyla yönetme

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

Oturum açma akışını Firebase Android SDK'sıyla işlemek için aşağıdaki adımları uygulayın:

  1. Sağlayıcı kimliği apple.com ile Builder'ı 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ıdan istemek istediğiniz varsayılan kapsamların dışında ek OAuth 2.0 kapsamları 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 etkinleştirildiğinde Firebase varsayılan olarak e-posta ve ad kapsamlarını ister. Bu ayarı E-posta adresi başına birden fazla hesap olarak değiştirirseniz Firebase, siz belirtmediğiniz sürece Apple'dan kapsam istemiyor.

  3. İsteğe bağlı: Apple'ın oturum açma ekranını İngilizce dışında bir dilde görüntülemek istiyorsanız locale parametresini ayarlayın. Desteklenen yerel ayarlar için Apple ile oturum açma dokümanlarına göz atı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ğrulama Diğer FirebaseAuth işlemlerinden farklı olarak bu işlemin, Özel Chrome Sekmesi açarak kullanıcı arayüzünüzün kontrolünü ele alacağını unutmayın. Bu nedenle, işlem kullanıcı arayüzünü başlattığında hemen ayrılacağından, eklediğiniz OnSuccessListener ve OnFailureListener öğelerinde Etkinliğinize referans vermeyin.

    Ö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, oturum açma akışı sırasında sistem tarafından yeniden alınabileceği anlamına gelir. Bu durumda kullanıcıyı tekrar denemeye zorlamamak için önceden bir sonuç olup olmadığını kontrol etmeniz gerekir.

    Bekleyen bir sonuç olup olmadığını kontrol etmek için getPendingAuthResult() işlevini çağırı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");
    }
    

    Beklemedeki sonuç yoksa startActivityForSignInWithProvider() çağrısı yaparak 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-posta adresini uygulamayla paylaşmayı tercih etmediğinde Apple, söz konusu kullanıcı için benzersiz bir e-posta adresi (xyz@privaterelay.appleid.com biçiminde) oluşturur 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, görünen ad gibi kullanıcı bilgilerini yalnızca kullanıcının ilk kez oturum açtığı uygulamalarla paylaşır. Firebase genellikle kullanıcının Apple ile ilk kez oturum açtığı sırada 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, yakın zamanda oturum açılmasını gerektiren hassas işlemler için yeni bir kimlik bilgisi almak üzere kullanabileceğiniz startActivityForReauthenticateWithProvider() ile kullanılabilir:

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, Apple hesaplarını diğer verilere bağlamadan önce kullanıcılardan açık izin almanızı zorunlu kılar.

Örneğin, bir Facebook hesabını mevcut Firebase hesabına bağlamak için kullanıcının Facebook'ta oturum açmasından elde ettiğiniz 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 işleme

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

  1. Her oturum açma isteği için rastgele bir dize ("tek seferlik") oluşturun. Aldığınız kimlik jetonunun, uygulamanızın kimlik doğrulama isteğine yanıt olarak özel olarak verildiğini doğrulamak için bu dizeyi kullanın. Bu adım, yeniden oynatma saldırılarını önlemek için önemlidir.

    Android'de SecureRandom ile aşağıdaki örnekte gösterildiği gibi kriptografik olarak güvenli bir tek kullanımlık şifreleme sayısı 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, tek seferlik şifrenin SHA246 karmasını 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 tek seferlik rastgele sayının SHA256 karmasını gönderirsiniz. Apple, bu karmayı yanıtta değiştirilmeden iletir. Firebase, orijinal tek seferlik şifreyi karma oluşturarak 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ış tek seferlik kimliği 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şturma işlemi uygulanmamış tek seferlik kimliği 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 bilgisini kullanarak Firebase ile 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şturma özelliğini destekleyen uygulamaların, App Store İnceleme Yönergeleri'nde açıklandığı gibi kullanıcıların hesaplarını uygulama içinden silmelerine izin vermesini 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'ı kullanarak 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'sini 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

    Kullanıcı ilk kez oturum açtıktan sonra yeni bir kullanıcı hesabı oluşturulur ve kullanıcının oturum açarken kullandığı kimlik bilgilerine (yani 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 nasıl oturum açtığından 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önet 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 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:

    Kotlin

    Firebase.auth.signOut()

    Java

    FirebaseAuth.getInstance().signOut();