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

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

قبل البدء

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

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

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

  • جهة الإصدار: سلسلة تحدّد موفّر الخدمة. يجب أن تكون هذه القيمة عنوان URL يشير إلى مكان مستند اكتشاف OIDC الخاص بالموفّر عند إلحاق /.well-known/openid-configuration به. على سبيل المثال، إذا كان جهة الإصدار هي 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. احفظ التغييرات.

التعامل مع مسار تسجيل الدخول باستخدام حزمة تطوير البرامج (SDK) لمنصّة Firebase

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

لمعالجة عملية تسجيل الدخول باستخدام حزمة تطوير البرامج (SDK) لنظام التشغيل Android من Firebase، اتّبِع الخطوات التالية:

  1. أنشئ مثيلًا من OAuthProvider باستخدام أداة الإنشاء مع معرّف موفِّر الخدمة

    Kotlin

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

    Java

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

  2. اختياري: حدِّد مَعلمات OAuth مخصّصة إضافية تريد إرسالها مع طلب OAuth.

    Kotlin

    // 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 وstate وscope وresponse_mode.

  3. اختياري: حدِّد نطاقات OAuth 2.0 الإضافية التي تريد طلبها من موفِّر المصادقة، والتي تتعدى الملف الشخصي الأساسي.

    Kotlin

    // 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

    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

    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

    // 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

    // 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

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

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();