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

إذا قمت بالترقية إلى Firebase Authentication with Identity Platform، فيمكنك مصادقة المستخدمين لديك باستخدام Firebase باستخدام الموفر المتوافق مع OpenID Connect (OIDC) الذي تختاره. وهذا يجعل من الممكن استخدام موفري الهوية الذين لا يدعمهم Firebase أصلاً.

قبل ان تبدأ

لتسجيل دخول المستخدمين باستخدام موفر OIDC، يجب عليك أولاً جمع بعض المعلومات من الموفر:

  • معرف العميل : سلسلة فريدة للموفر تحدد تطبيقك. قد يقوم مزود الخدمة الخاص بك بتعيين معرف عميل مختلف لكل نظام أساسي تدعمه. هذه إحدى قيم مطالبة aud في رموز المعرف الصادرة عن مزود الخدمة الخاص بك.

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

  • المُصدر : سلسلة تحدد المزود الخاص بك. يجب أن تكون هذه القيمة عبارة عن عنوان 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 باستخدام Identity Platform، فقم بذلك. مصادقة OpenID Connect متاحة فقط في المشاريع التي تمت ترقيتها.

  3. في صفحة موفري تسجيل الدخول بوحدة تحكم Firebase، انقر فوق إضافة موفر جديد ، ثم انقر فوق OpenID Connect .

  4. حدد ما إذا كنت ستستخدم تدفق رمز التفويض أو تدفق المنح الضمني .

    يجب عليك دائمًا استخدام تدفق التعليمات البرمجية إذا كان مزود الخدمة الخاص بك يدعمه . يعتبر التدفق الضمني أقل أمانًا ولا يُنصح باستخدامه بشدة.

  5. إعطاء اسم لهذا المزود. لاحظ معرف الموفر الذي تم إنشاؤه: شيء مثل oidc.example-provider . ستحتاج إلى هذا المعرف عند إضافة رمز تسجيل الدخول إلى تطبيقك.

  6. حدد معرف العميل الخاص بك وسر العميل، وسلسلة المُصدر الخاصة بموفر الخدمة الخاص بك. يجب أن تتطابق هذه القيم تمامًا مع القيم التي عيّنها لك مزود الخدمة.

  7. احفظ تغييراتك.

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

إذا كنت تقوم بإنشاء تطبيق Android، فإن أسهل طريقة لمصادقة المستخدمين لديك باستخدام Firebase باستخدام موفر OIDC الخاص بك هي التعامل مع تدفق تسجيل الدخول بالكامل باستخدام Firebase Android SDK.

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

  1. قم بإنشاء مثيل لـ OAuthProvider باستخدام منشئه باستخدام معرف الموفر

    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", "user@example.com")

    Java

    // Target specific email with login hint.
    providerBuilder.addCustomParameter("login_hint", "user@example.com");

    تحقق مع موفر OIDC الخاص بك لمعرفة المعلمات التي يدعمها. لاحظ أنه لا يمكنك تمرير المعلمات المطلوبة لـ Firebase باستخدام setCustomParameters() . هذه المعلمات هي Client_id و response_type و redirect_uri والحالة والنطاق و 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 وقواعد أمان التخزين السحابي، يمكنك الحصول على معرف المستخدم الفريد للمستخدم الذي قام بتسجيل الدخول من متغير auth ، واستخدامه للتحكم في البيانات التي يمكن للمستخدم الوصول إليها.

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

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

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();