Check out what’s new from Firebase at Google I/O 2022. Learn more

אימות באמצעות אפל באנדרואיד

אתה יכול לאפשר למשתמשים שלך לבצע אימות עם Firebase באמצעות Apple ID שלהם על ידי שימוש ב-Firebase SDK כדי לבצע את זרימת הכניסה מקצה לקצה OAuth 2.0.

לפני שאתה מתחיל

כדי להיכנס למשתמשים באמצעות Apple, תחילה הגדר את ה- Sign In with Apple באתר המפתחים של Apple, ולאחר מכן הפעל את Apple כספק כניסה לפרויקט Firebase שלך.

הצטרף לתוכנית המפתחים של אפל

ניתן להגדיר כניסה עם אפל רק על ידי חברי תוכנית המפתחים של אפל .

הגדר כניסה עם אפל

באתר Apple Developer , בצע את הפעולות הבאות:

  1. שייך את האתר שלך לאפליקציה שלך כמתואר בסעיף הראשון של הגדר כניסה עם Apple לאינטרנט . כאשר תתבקש, רשום את כתובת האתר הבאה ככתובת URL להחזרה:

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

    אתה יכול לקבל את מזהה הפרויקט שלך ב- Firebase בדף ההגדרות של מסוף Firebase .

    כשתסיים, שים לב למזהה השירות החדש שלך, שתזדקק לו בסעיף הבא.

  2. צור כניסה עם מפתח פרטי של Apple . תזדקק למפתח הפרטי ומזהה המפתח החדש שלך בסעיף הבא.
  3. אם אתה משתמש באחת מהתכונות של Firebase Authentication ששולחות אימיילים למשתמשים, כולל כניסה לקישור אימייל, אימות כתובת דוא"ל, ביטול שינוי חשבון ואחרות, הגדר את שירות ממסר הדוא"ל הפרטי של Apple noreply@ YOUR_FIREBASE_PROJECT_ID .firebaseapp.com (או דומיין תבנית הדוא"ל המותאם אישית שלך) כך שאפל תוכל להעביר הודעות דוא"ל שנשלחות על ידי אימות Firebase לכתובות דוא"ל אנונימיות של Apple.

אפשר את Apple כספק כניסה

  1. הוסף את Firebase לפרויקט Android שלך . הקפד לרשום את חתימת ה-SHA-1 של האפליקציה שלך כאשר אתה מגדיר את האפליקציה שלך במסוף Firebase.
  2. במסוף Firebase , פתח את הקטע Auth . בכרטיסייה שיטת כניסה , הפעל את ספק Apple . ציין את מזהה השירות שיצרת בסעיף הקודם. כמו כן, בסעיף תצורת זרימת קוד OAuth , ציין את מזהה צוות Apple שלך ​​ואת המפתח הפרטי ומזהה המפתח שיצרת בסעיף הקודם.

עמוד בדרישות הנתונים האנונימיים של Apple

כניסה עם אפל נותנת למשתמשים אפשרות להפוך את הנתונים שלהם לאנונימיים, כולל כתובת הדוא"ל שלהם, בעת הכניסה. למשתמשים שבוחרים באפשרות זו יש כתובות דוא"ל עם הדומיין privaterelay.appleid.com . כאשר אתה משתמש בכניסה עם Apple באפליקציה שלך, עליך לציית לכל מדיניות מפתחים או תנאים רלוונטיים של Apple לגבי מזהי Apple אנונימיים אלה.

זה כולל קבלת כל הסכמת משתמש נדרשת לפני שאתה משייך מידע אישי מזהה ישיר עם מזהה Apple אנונימי. בעת שימוש באימות Firebase, זה עשוי לכלול את הפעולות הבאות:

  • קשר כתובת אימייל למזהה Apple אנונימי או להיפך.
  • קשר מספר טלפון למזהה Apple אנונימי או להיפך
  • קשר אישור חברתי לא אנונימי (פייסבוק, גוגל וכו') למזהה Apple אנונימי או להיפך.

הרשימה לעיל אינה ממצה. עיין בהסכם הרישיון של Apple Developer Program בסעיף החברות בחשבון המפתח שלך כדי לוודא שהאפליקציה שלך עומדת בדרישות של Apple.

טפל בזרימת הכניסה עם Firebase SDK

ב-Android, הדרך הקלה ביותר לאמת את המשתמשים שלך עם Firebase באמצעות חשבונות Apple שלהם היא לטפל בכל זרימת הכניסה עם Firebase Android SDK.

כדי לטפל בזרימת הכניסה עם Firebase Android SDK, בצע את השלבים הבאים:

  1. בנו מופע של OAuthProvider באמצעות ה-Builder שלו עם מזהה הספק apple.com :

    Java

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

    Kotlin+KTX

    val provider = OAuthProvider.newBuilder("apple.com")
    
  2. אופציונלי: ציין היקפי OAuth 2.0 נוספים מעבר לברירת המחדל שברצונך לבקש מספק האימות.

    Java

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

    Kotlin+KTX

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

    כברירת מחדל, כאשר חשבון אחד לכל כתובת אימייל מופעל, Firebase מבקש היקפי אימייל ושמות. אם תשנה את ההגדרה הזו למספר חשבונות לכל כתובת אימייל , Firebase לא יבקש היקפים מאפל אלא אם תציין אותם.

  3. אופציונלי: אם ברצונך להציג את מסך הכניסה של אפל בשפה שאינה אנגלית, הגדר את פרמטר locale . ראה את ה- Sign In with Apple Docs עבור המקומות הנתמכים.

    Java

    // 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 , זה ישתלט על ממשק המשתמש שלך על ידי פתיחת כרטיסיית Chrome מותאמת אישית. כתוצאה מכך, אל תתייחס לפעילות שלך ב- OnSuccessListener וב- OnFailureListener שאתה מצרף מכיוון שהם יתנתקו מיד כאשר הפעולה תתחיל את ממשק המשתמש.

    תחילה עליך לבדוק אם כבר קיבלת תשובה. כניסה בשיטה זו מציבה את הפעילות שלך ברקע, מה שאומר שניתן להחזיר אותה על ידי המערכת במהלך זרימת הכניסה. על מנת לוודא שלא תגרום למשתמש לנסות שוב אם זה קורה, עליך לבדוק אם כבר קיימת תוצאה.

    כדי לבדוק אם יש תוצאה ממתינה, קרא getPendingAuthResult() :

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

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

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

    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, אפל לא מספקת כתובת URL של תמונה.

    כמו כן, כאשר המשתמש בוחר לא לשתף את האימייל שלו עם האפליקציה, אפל מספקת כתובת דוא"ל ייחודית עבור אותו משתמש (בצורה xyz@privaterelay.appleid.com ), אותה היא חולקת עם האפליקציה שלך. אם הגדרתם את שירות ממסר הדוא"ל הפרטי, אפל מעבירה מיילים שנשלחו לכתובת האנונימית לכתובת האימייל האמיתית של המשתמש.

    Apple משתפת רק מידע משתמש כגון שם התצוגה עם יישומים בפעם הראשונה שמשתמש נכנס. בדרך כלל, Firebase מאחסן את שם התצוגה בפעם הראשונה שמשתמש נכנס ל-Apple, אותו תוכל לקבל באמצעות getCurrentUser().getDisplayName() . עם זאת, אם השתמשת בעבר ב-Apple כדי להיכנס משתמש לאפליקציה מבלי להשתמש ב-Firebase, Apple לא תספק ל-Firebase את שם התצוגה של המשתמש.

אימות מחדש וקישור חשבון

ניתן להשתמש באותה דפוס עם startActivityForReauthenticateWithProvider() שבו אתה יכול להשתמש כדי לאחזר אישור חדש עבור פעולות רגישות הדורשות כניסה אחרונה:

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

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 שלהם לנתונים אחרים.

לדוגמה, כדי לקשר חשבון פייסבוק לחשבון Firebase הנוכחי, השתמש באסימון הגישה שקיבלת מהכניסה של המשתמש לפייסבוק:

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

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 באמצעות חשבון Apple על ידי טיפול בזרימת הכניסה על ידי שימוש ב-Apple Sign-In JS SDK, בנייה ידנית של זרימת OAuth או על ידי שימוש בספריית OAuth כגון AppAuth .

  1. עבור כל בקשת כניסה, צור מחרוזת אקראית - "nonce" - שבה תשתמש כדי לוודא שאסימון הזיהוי שתקבל הוענק במיוחד בתגובה לבקשת האימות של האפליקציה שלך. שלב זה חשוב כדי למנוע התקפות חוזרות.

    אתה יכול ליצור nonce מאובטח מבחינה קריפטוגרפית באנדרואיד עם SecureRandom , כמו בדוגמה הבאה:

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

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

    לאחר מכן, קבל את ה-hash SHA246 של ה-nonce כמחרוזת hex:

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

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

    אתה תשלח את ה-hash SHA256 של nonce עם בקשת הכניסה שלך, שאפל תעביר ללא שינוי בתגובה. Firebase מאמת את התגובה על ידי hashing של ה-nonce המקורי והשוואתה לערך שהעביר אפל.

  2. התחל את זרימת הכניסה של Apple באמצעות ספריית OAuth שלך או שיטה אחרת. הקפד לכלול את ה-hash nonce כפרמטר בבקשה שלך.

  3. לאחר שתקבל את התגובה של אפל, קבל את אסימון המזהה מהתגובה והשתמש בו ובאי-גיבוב ללא גיבוב כדי ליצור AuthCredential :

    Java

    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:

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

    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 :

Java

FirebaseAuth.getInstance().signOut();

Kotlin+KTX

Firebase.auth.signOut()