אימות באמצעות OpenID Connect ב-Android

אם שדרגת ל-Firebase Authentication with Identity Platform, תוכל לאמת את המשתמשים שלך באמצעות Firebase באמצעות ספק תואם OpenID Connect (OIDC) לבחירתכם. הזה מאפשרת להשתמש בספקי זהויות שלא נתמכים במקור על ידי Firebase.

לפני שמתחילים

כדי להכניס משתמשים באמצעות ספק OIDC, קודם צריך לאסוף מידע מסוים מהספק:

  • Client ID: מחרוזת ייחודית לספק שמזהה את האפליקציה שלכם. שלך יכול להיות שהספק יקצה לכם מזהה לקוח שונה לכל פלטפורמה שבה אתם תומכים. זהו אחד מהערכים של הבקשה aud באסימונים מזהים שהונפקו על ידי ספק.

  • סוד לקוח: מחרוזת סוד שדרכה הספק מאמת את הבעלות על מזהה לקוח. לכל מזהה לקוח צריך סוד לקוח תואם. (הערך הזה נדרש רק אם אתם משתמשים בתהליך קוד האימות, שמומלץ מאוד להשתמש בו).

  • Issuer: מחרוזת שמזהה את הספק. הערך הזה חייב להיות כתובת URL שמצורף ל-/.well-known/openid-configuration, הוא המיקום של מסמך הגילוי מסוג OIDC של הספק. לדוגמה, אם המנפיק הוא https://auth.example.com, מסמך הגילוי חייב להיות זמין בכתובת https://auth.example.com/.well-known/openid-configuration.

אחרי שמקבלים את המידע שלמעלה, מפעילים את OpenID Connect כספק כניסה לפרויקט ב-Firebase:

  1. מוסיפים את Firebase לפרויקט Android.

  2. אם עדיין לא שדרגתם ל-Firebase Authentication with Identity Platform, עליכם לעשות זאת. אימות OpenID Connect זמין רק בפרויקטים משודרגים.

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

  4. בוחרים אם להשתמש בהרשאה באמצעות קוד או הענקת זרם הענקת גישה משתמע.

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

  5. נותנים שם לספק הזה. שימו לב למזהה הספק שנוצר: oidc.example-provider. צריך להשתמש במזהה הזה כדי להוסיף קוד כניסה לאפליקציה.

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

  7. שומרים את השינויים.

איך מבצעים את תהליך הכניסה באמצעות Firebase SDK

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

כדי לבצע את תהליך הכניסה באמצעות ה-Android SDK של Firebase, צריך לבצע את השלבים הבאים:

  1. יצירה של מופע של OAuthProvider באמצעות Builder שלו עם מזהה הספק

    Kotlin+KTX

    val providerBuilder = OAuthProvider.newBuilder("oidc.example-provider")

    Java

    OAuthProvider.Builder providerBuilder = OAuthProvider.newBuilder("oidc.example-provider");

  2. אופציונלי: מציינים פרמטרים מותאמים אישית נוספים של OAuth שרוצים להגדיר שליחה עם בקשת ה-OAuth.

    Kotlin+KTX

    // Target specific email with login hint.
    providerBuilder.addCustomParameter("login_hint", "[email protected]")

    Java

    // Target specific email with login hint.
    providerBuilder.addCustomParameter("login_hint", "[email protected]");

    כדאי לבדוק עם ספק ה-OIDC בשביל הפרמטרים שהוא תומך בהם. שימו לב שאי אפשר להעביר פרמטרים שנדרשים ל-Firebase עם setCustomParameters() הפרמטרים האלה הם client_id, response_type, redirect_uri, state, scope וגם response_mode.

  3. אופציונלי: מציינים היקפי הרשאות OAuth 2.0 נוספים מעבר לפרופיל הבסיסי שרוצים לבקש מספק האימות.

    Kotlin+KTX

    // Request read access to a user's email addresses.
    // This must be preconfigured in the app's API permissions.
    providerBuilder.scopes = listOf("mail.read", "calendars.read")

    Java

    // Request read access to a user's email addresses.
    // This must be preconfigured in the app's API permissions.
    List<String> scopes =
            new ArrayList<String>() {
                {
                    add("mail.read");
                    add("calendars.read");
                }
            };
    providerBuilder.setScopes(scopes);

    כדאי לברר עם ספק ה-OIDC בשביל היקפי ההרשאות שהוא משתמש בהם.

  4. מבצעים אימות עם Firebase באמצעות אובייקט של ספק OAuth. שימו לב שבניגוד ל- FirebaseAuth אחר הפעולה הזאת תקבל שליטה על ממשק המשתמש שלך על ידי כרטיסיית Chrome בהתאמה אישית. כתוצאה מכך, אין להפנות לפעילות שלך בOnSuccessListener ו-OnFailureListener שתחבר, כי הם יתנתקו מיד הפעולה מפעילה את ממשק המשתמש.

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

    כדי לבדוק אם יש תוצאה בהמתנה, צריך להתקשר למספר getPendingAuthResult:

    Kotlin+KTX

    val pendingResultTask = firebaseAuth.pendingAuthResult
    if (pendingResultTask != null) {
        // There's something already here! Finish the sign-in for your user.
        pendingResultTask
            .addOnSuccessListener {
                // User is signed in.
                // IdP data available in
                // authResult.getAdditionalUserInfo().getProfile().
                // The OAuth access token can also be retrieved:
                // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                // The OAuth secret can be retrieved by calling:
                // ((OAuthCredential)authResult.getCredential()).getSecret().
            }
            .addOnFailureListener {
                // Handle failure.
            }
    } else {
        // There's no pending result so you need to start the sign-in flow.
        // See below.
    }

    Java

    Task<AuthResult> pendingResultTask = firebaseAuth.getPendingAuthResult();
    if (pendingResultTask != null) {
        // There's something already here! Finish the sign-in for your user.
        pendingResultTask
                .addOnSuccessListener(
                        new OnSuccessListener<AuthResult>() {
                            @Override
                            public void onSuccess(AuthResult authResult) {
                                // User is signed in.
                                // IdP data available in
                                // authResult.getAdditionalUserInfo().getProfile().
                                // The OAuth access token can also be retrieved:
                                // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                                // The OAuth secret can be retrieved by calling:
                                // ((OAuthCredential)authResult.getCredential()).getSecret().
                            }
                        })
                .addOnFailureListener(
                        new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                // Handle failure.
                            }
                        });
    } else {
        // There's no pending result so you need to start the sign-in flow.
        // See below.
    }

    כדי להתחיל את תהליך הכניסה, צריך לקרוא ל-startActivityForSignInWithProvider:

    Kotlin+KTX

    firebaseAuth
        .startActivityForSignInWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // User is signed in.
            // IdP data available in
            // authResult.getAdditionalUserInfo().getProfile().
            // The OAuth access token can also be retrieved:
            // ((OAuthCredential)authResult.getCredential()).getAccessToken().
            // The OAuth secret can be retrieved by calling:
            // ((OAuthCredential)authResult.getCredential()).getSecret().
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    firebaseAuth
            .startActivityForSignInWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // User is signed in.
                            // IdP data available in
                            // authResult.getAdditionalUserInfo().getProfile().
                            // The OAuth access token can also be retrieved:
                            // ((OAuthCredential)authResult.getCredential()).getAccessToken().
                            // The OAuth secret can be retrieved by calling:
                            // ((OAuthCredential)authResult.getCredential()).getSecret().
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

  5. הדוגמאות שלמעלה מתמקדות בתהליכי הכניסה, אבל יש גם יכולת לקשר ספק OIDC למשתמש קיים באמצעות startActivityForLinkWithProvider לדוגמה, אפשר לקשר מספר ספקים לאותו משתמש, כדי לאפשר להם להיכנס עם אחד מהם.

    Kotlin+KTX

    // The user is already signed-in.
    val firebaseUser = firebaseAuth.currentUser!!
    firebaseUser
        .startActivityForLinkWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // Provider credential is linked to the current user.
            // IdP data available in
            // authResult.getAdditionalUserInfo().getProfile().
            // The OAuth access token can also be retrieved:
            // authResult.getCredential().getAccessToken().
            // The OAuth secret can be retrieved by calling:
            // authResult.getCredential().getSecret().
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    // The user is already signed-in.
    FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
    
    firebaseUser
            .startActivityForLinkWithProvider(/* activity= */ this, provider.build())
            .addOnSuccessListener(
                    new OnSuccessListener<AuthResult>() {
                        @Override
                        public void onSuccess(AuthResult authResult) {
                            // Provider credential is linked to the current user.
                            // IdP data available in
                            // authResult.getAdditionalUserInfo().getProfile().
                            // The OAuth access token can also be retrieved:
                            // authResult.getCredential().getAccessToken().
                            // The OAuth secret can be retrieved by calling:
                            // authResult.getCredential().getSecret().
                        }
                    })
            .addOnFailureListener(
                    new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Handle failure.
                        }
                    });

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

    Kotlin+KTX

    // The user is already signed-in.
    val firebaseUser = firebaseAuth.currentUser!!
    firebaseUser
        .startActivityForReauthenticateWithProvider(activity, provider.build())
        .addOnSuccessListener {
            // User is re-authenticated with fresh tokens and
            // should be able to perform sensitive operations
            // like account deletion and email or password
            // update.
        }
        .addOnFailureListener {
            // Handle failure.
        }

    Java

    // The user is already signed-in.
    FirebaseUser firebaseUser = firebaseAuth.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.
                        }
                    });

איך מטפלים בתהליך הכניסה באופן ידני

אם כבר הטמעתם באפליקציה את תהליך הכניסה באמצעות OpenID Connect, יכולים להשתמש ישירות באסימון המזהה כדי לבצע אימות מול Firebase:

Kotlin+KTX

val providerId = "oidc.example-provider" // As registered in Firebase console.
val credential = oAuthCredential(providerId) {
    setIdToken(idToken) // ID token from OpenID Connect flow.
}
Firebase.auth
    .signInWithCredential(credential)
    .addOnSuccessListener { authResult ->
        // User is signed in.

        // IdP data available in:
        //    authResult.additionalUserInfo.profile
    }
    .addOnFailureListener { e ->
        // Handle failure.
    }

Java

AuthCredential credential = OAuthProvider
        .newCredentialBuilder("oidc.example-provider")  // As registered in Firebase console.
        .setIdToken(idToken)  // ID token from OpenID Connect flow.
        .build();
FirebaseAuth.getInstance()
        .signInWithCredential(credential)
        .addOnSuccessListener(new OnSuccessListener<AuthResult>() {
            @Override
            public void onSuccess(AuthResult authResult) {
                // User is signed in.

                // IdP data available in:
                //    authResult.getAdditionalUserInfo().getProfile()
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // Handle failure.
            }
        });

השלבים הבאים

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

  • באפליקציות, אפשר לקבל את פרטי הפרופיל הבסיסיים של המשתמש מהאובייקט FirebaseUser. ראו ניהול משתמשים.

  • בכללי האבטחה של Firebase Realtime Database ו-Cloud Storage, אפשר לקבל את מזהה המשתמש הייחודי של המשתמש שנכנס לחשבון מהמשתנה auth, ולהשתמש בו כדי לקבוע לאילו נתונים למשתמש תהיה גישה.

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

כדי לנתק משתמש מהחשבון, יש להתקשר אל signOut:

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();