المصادقة باستخدام Apple على Android

يمكنك السماح للمستخدمين بالمصادقة مع Firebase باستخدام معرف Apple الخاص بهم باستخدام Firebase SDK لتنفيذ تدفق تسجيل الدخول من طرف إلى طرف OAuth 2.0.

قبل ان تبدأ

لتسجيل دخول المستخدمين باستخدام Apple ، قم أولاً بتكوين Sign In with Apple على موقع مطوري Apple ، ثم قم بتمكين Apple كموفر تسجيل الدخول لمشروع Firebase الخاص بك.

انضم إلى برنامج Apple Developer Program

تسجيل الدخول مع يمكن تكوين أبل فقط من قبل أعضاء المطور أبل برنامج .

قم بتكوين تسجيل الدخول مع Apple

على المطور أبل الموقع، القيام بما يلي:

  1. ربط موقع الويب الخاص بك إلى التطبيق الخاص بك كما هو موضح في القسم الأول من تكوين تسجيل الدخول مع أبل لشبكة الإنترنت . عند المطالبة ، قم بتسجيل عنوان URL التالي كعنوان URL للعودة:

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

    يمكنك الحصول على اسم المستخدم الخاص بك مشروع Firebase على الصفحة حدة Firebase الإعدادات .

    عند الانتهاء ، قم بتدوين معرف الخدمة الجديد الخاص بك ، والذي ستحتاج إليه في القسم التالي.

  2. إنشاء تسجيل الدخول مع مفتاح أبل الخاص . ستحتاج إلى مفتاحك الخاص الجديد ومعرف المفتاح في القسم التالي.
  3. إذا كنت تستخدم أي من الميزات مصادقة Firebase أن ترسل رسائل البريد الإلكتروني للمستخدمين، بما في ذلك البريد الإلكتروني رابط تسجيل الدخول، التحقق من عنوان البريد الإلكتروني، وتغيير حساب الإلغاء، وغيرها، و تكوين خدمة الترحيل البريد الإلكتروني الخاصة أبل وتسجيل noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com (أو مجال قالب البريد الإلكتروني المخصص الخاص بك) حتى تتمكن Apple من ترحيل رسائل البريد الإلكتروني المرسلة بواسطة مصادقة Firebase إلى عناوين بريد إلكتروني مجهولة الهوية من Apple.

قم بتمكين Apple كموفر لتسجيل الدخول

  1. إضافة Firebase إلى مشروع Android . تأكد من تسجيل توقيع SHA-1 لتطبيقك عند إعداد تطبيقك في وحدة تحكم Firebase.
  2. في وحدة التحكم Firebase ، فتح الباب أصيل. على علامة التبويب تسجيل الدخول الأسلوب، تمكين مزود أبل. حدد معرّف الخدمة الذي أنشأته في القسم السابق. أيضا، في مقطع التكوين تدفق كود أوث، حدد الخاص بك أبل فريق ID والمفتاح الخاص وID المفاتيح التي تم إنشاؤها في المقطع السابق.

الامتثال لمتطلبات البيانات المجهولة الهوية من Apple

تسجيل الدخول مع أبل تتيح للمستخدمين خيار إخفاء الهوية البيانات الخاصة بهم، بما في ذلك عناوين بريدهم الإلكتروني، عند تسجيل الدخول. المستخدمين الذين يختارون هذا الخيار يكون عناوين البريد الإلكتروني مع المجال privaterelay.appleid.com . عند استخدام تسجيل الدخول مع Apple في تطبيقك ، يجب عليك الامتثال لأي سياسات مطور أو شروط مطبقة من Apple فيما يتعلق بمعرفات Apple المجهولة الهوية.

يتضمن ذلك الحصول على أي موافقة مطلوبة من المستخدم قبل ربط أي معلومات شخصية تحدد الهوية مباشرة بمعرف Apple المجهول. عند استخدام مصادقة Firebase ، قد يشمل ذلك الإجراءات التالية:

  • اربط عنوان بريد إلكتروني بمعرف Apple المجهول أو العكس.
  • اربط رقم هاتف بمعرف Apple المجهول أو العكس
  • اربط بيانات اعتماد اجتماعية غير مجهولة (Facebook و Google وما إلى ذلك) بمعرف Apple المجهول أو العكس.

القائمة أعلاه ليست شاملة. راجع اتفاقية ترخيص برنامج مطوري Apple في قسم العضوية لحساب المطور الخاص بك للتأكد من أن تطبيقك يلبي متطلبات Apple.

تعامل مع تدفق تسجيل الدخول باستخدام Firebase SDK

على نظام التشغيل Android ، تتمثل أسهل طريقة لمصادقة المستخدمين باستخدام Firebase باستخدام حسابات Apple الخاصة بهم في التعامل مع تدفق تسجيل الدخول بالكامل باستخدام Firebase Android SDK.

للتعامل مع تدفق تسجيل الدخول باستخدام Firebase Android SDK ، اتبع الخطوات التالية:

  1. بناء مثيل OAuthProvider باستخدام بناء مع معرف مزود apple.com :

    جافا

    OAuthProvider.Builder provider = OAuthProvider.newBuilder("apple.com");
    

    Kotlin + KTX

    val provider = OAuthProvider.newBuilder("apple.com")
    
  2. اختياري: حدد أوث إضافي 2.0 نطاقات خارج الافتراضي الذي تريد طلب من مزود المصادقة.

    جافا

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

    Kotlin + KTX

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

    افتراضيا، عند تمكين حساب واحد لكل عنوان البريد الإلكتروني، وتطلب Firebase البريد الإلكتروني واسم نطاقات. إذا قمت بتغيير هذا الإعداد إلى حسابات متعددة في عنوان البريد الإلكتروني، Firebase لا يطلب أي نطاقات من أبل ما لم تحدده لهم.

  3. اختياري: إذا كنت ترغب في عرض تسجيل الدخول أبل الشاشة في لغة أخرى غير الإنجليزية، تعيين locale المعلمة. انظر تسجيل الدخول مع مستندات أبل لغات معتمدة.

    جافا

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

    Kotlin + KTX

    // Localize the Apple authentication screen in French.
    provider.addCustomParameter("locale", "fr")
    
  4. مصادقة مع Firebase باستخدام كائن موفر OAuth. علما بأن خلافا لغيرها من FirebaseAuth العمليات، وهذا سوف السيطرة على واجهة المستخدم عن طريق فتح علامة تبويب كروم مخصص. ونتيجة لذلك، لا مرجع آخر الخاصة بك في OnSuccessListener و OnFailureListener التي توصلها لأنها سوف فصل فورا عندما تبدأ تشغيل واجهة المستخدم.

    يجب عليك أولاً التحقق مما إذا كنت قد تلقيت ردًا بالفعل. يؤدي تسجيل الدخول بهذه الطريقة إلى وضع نشاطك في الخلفية ، مما يعني أنه يمكن للنظام استعادته أثناء تدفق تسجيل الدخول. للتأكد من عدم قيام المستخدم بالمحاولة مرة أخرى في حالة حدوث ذلك ، يجب عليك التحقق مما إذا كانت النتيجة موجودة بالفعل.

    للتحقق مما إذا كان هناك نتيجة المعلقة، استدعاء 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");
    }
    

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

    اذا لم يكن هناك نتيجة المعلقة، بدء تسجيل الدخول التدفق، من خلال الدعوة 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);
                        }
                    });
    

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

    على عكس الموفرين الآخرين المدعومين بواسطة Firebase Auth ، لا تقدم Apple عنوان URL للصورة.

    أيضا، عندما يختار المستخدم ليس لتبادل البريد الإلكتروني الخاصة بهم مع التطبيق، أحكام أبل عنوان بريد إلكتروني فريد لهذا المستخدم (النموذج xyz@privaterelay.appleid.com )، وهو ما أسهم مع التطبيق الخاص بك. إذا قمت بتكوين خدمة ترحيل البريد الإلكتروني الخاص ، فإن Apple تعيد توجيه رسائل البريد الإلكتروني المرسلة إلى العنوان المجهول إلى عنوان البريد الإلكتروني الحقيقي للمستخدم.

    التفاح المعلومات سهم فقط المستخدم مثل اسم العرض مع التطبيقات أول مرة قيام المستخدم بتسجيل الدخول. عادة، Firebase مخازن اسم العرض أول مرة قيام المستخدم بتسجيل الدخول مع أبل، والتي يمكنك الحصول عليها مع 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.
          }
        });

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

و، يمكنك استخدام 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.
        }
      }
    });

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

متقدم: تعامل مع تدفق تسجيل الدخول يدويًا

يمكنك أيضا المصادقة مع Firebase باستخدام حساب أبل من خلال التعامل مع علامة في تدفق إما عن طريق استخدام أبل الدخول في JS SDK، وبناء تدفق أوث يدويا أو باستخدام مكتبة أوث مثل AppAuth .

  1. لكل طلب تسجيل دخول ، أنشئ سلسلة عشوائية - "nonce" - والتي ستستخدمها للتأكد من أن رمز المعرف المميز الذي تحصل عليه قد تم منحه استجابةً لطلب مصادقة التطبيق الخاص بك على وجه التحديد. هذه الخطوة مهمة لمنع هجمات الإعادة.

    يمكنك إنشاء حالية آمن مشفر على الروبوت مع 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();
    }
    

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

    بعد ذلك ، احصل على تجزئة SHA246 للرمز nonce كسلسلة سداسية عشرية:

    جافا

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

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

    سترسل تجزئة SHA256 لـ nonce مع طلب تسجيل الدخول ، والذي ستمرره Apple دون تغيير في الاستجابة. يتحقق Firebase من الاستجابة عن طريق تجزئة الرقم الأصلي غير القياسي ومقارنته بالقيمة التي تم تمريرها بواسطة Apple.

  2. ابدأ تدفق تسجيل الدخول إلى Apple باستخدام مكتبة OAuth أو طريقة أخرى. تأكد من تضمين nonce المجزأ كمعامل في طلبك.

  3. بعد تتلقى استجابة أبل، احصل على ID رمزية من الاستجابة واستخدامها وحالية unhashed لخلق AuthCredential :

    جافا

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

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

    Kotlin + KTX

    auth.signInWithCredential(credential)
          .addOnCompleteListener(this) { task ->
              if (task.isSuccessful) {
                // User successfully signed in with Apple ID token.
                // ...
              }
          }
    

اذا كانت الدعوة إلى signInWithCredential نجحت، يمكنك استخدام getCurrentUser طريقة للحصول على بيانات حساب المستخدم.

الخطوات التالية

بعد أن يقوم المستخدم بتسجيل الدخول لأول مرة ، يتم إنشاء حساب مستخدم جديد وربطه ببيانات الاعتماد - أي اسم المستخدم وكلمة المرور أو رقم الهاتف أو معلومات موفر المصادقة - المستخدم الذي قام بتسجيل الدخول باستخدام. يتم تخزين هذا الحساب الجديد كجزء من مشروع Firebase الخاص بك ، ويمكن استخدامه لتحديد هوية مستخدم عبر كل تطبيق في مشروعك ، بغض النظر عن كيفية تسجيل المستخدم للدخول.

  • في التطبيقات الخاصة بك، يمكنك الحصول على المعلومات الشخصية الأساسية للمستخدم من FirebaseUser الكائن. انظر إدارة المستخدمين .

  • في قاعدة البيانات الخاصة بك Firebase الحقيقي وسحابة التخزين قواعد الأمن ، يمكنك الحصول على قعت في هوية المستخدم الفريد المستخدم من auth متغير، واستخدامها للسيطرة على ما هي البيانات على وصول ويمكن للمستخدم.

يمكنك السماح للمستخدمين تسجيل الدخول إلى التطبيق الخاص بك باستخدام موفري المصادقة متعددة عن طريق ربط المصادقة أوراق اعتماد مقدم إلى حساب مستخدم موجود.

تسجيل الخروج مستخدم، استدعاء signOut :

جافا

FirebaseAuth.getInstance().signOut();

Kotlin + KTX

Firebase.auth.signOut()