تمكين المصادقة في تطبيق Android الخاص بك باستخدام Microsoft Azure Active Directory B2C

توضح لك هذه المقالة كيفية إضافة مصادقة AAD (دليل Azure النشط) متاجرة عمل-مستهلك (Azure AD B2C) إلى تطبيق Android المحمول الخاص بك.

استخدم هذه المقالة مع تكوين المصادقة في نموذج تطبيق Android باستخدام Azure AD B2C، واستبدال نموذج تطبيق Android بتطبيق Android الخاص بك. بعد إكمال الإرشادات الواردة في هذه المقالة، سيقبل تطبيقك عمليات تسجيل الدخول عبر Microsoft Azure Active Directory B2C.

المتطلبات الأساسية

راجع المتطلبات الأساسية وإرشادات التكامل في تكوين المصادقة في نموذج تطبيق Android باستخدام Azure AD B2C.

أنشئ مشروعًا لتطبيق Android

إذا لم يكن لديك تطبيق Android بالفعل، فقم بإعداد مشروع جديد عن طريق القيام بما يلي:

  1. في استوديو Android، حدد Start a new Android Studio project.
  2. حدد Basic Activity، ثم حدد Next.
  3. قم بتسمية تطبيقك.
  4. احفظ اسم الحزمة. ستدخله لاحقًا في مدخل Microsoft Azure.
  5. قم بتغيير اللغة من Kotlin إلى Java.
  6. عيّن Minimum API level على API 19 أو أعلى، ثم حدد Finish.
  7. في طريقة عرض المشروع، اخترProject في القائمة المنسدلة لعرض ملفات المشروع المصدر وغير المصدر، وافتح app / build.gradle، ثم اضبط targetSdkVersion على 28.

الخطوة 1: قم بتركيب التبعيات

في نافذة مشروع استوديو Android، انتقل إلىapp>build.gradle، ثم أضف ما يلي:

apply plugin: 'com.android.application'

allprojects {
    repositories {
    mavenCentral()
    google()
    mavenLocal()
    maven {
        url 'https://pkgs.dev.azure.com/MicrosoftDeviceSDK/DuoSDK-Public/_packaging/Duo-SDK-Feed/maven/v1'
    }
    maven {
        name "vsts-maven-adal-android"
        url "https://identitydivision.pkgs.visualstudio.com/_packaging/AndroidADAL/maven/v1"
        credentials {
            username System.getenv("ENV_VSTS_MVN_ANDROIDADAL_USERNAME") != null ? System.getenv("ENV_VSTS_MVN_ANDROIDADAL_USERNAME") : project.findProperty("vstsUsername")
            password System.getenv("ENV_VSTS_MVN_ANDROIDADAL_ACCESSTOKEN") != null ? System.getenv("ENV_VSTS_MVN_ANDROIDADAL_ACCESSTOKEN") : project.findProperty("vstsMavenAccessToken")
        }
    }
    jcenter()
    }
}
dependencies{
    implementation 'com.microsoft.identity.client:msal:2.+'
    }
packagingOptions{
    exclude("META-INF/jersey-module-version")
}

الخطوة 2: أضف مكونات المصادقة

تتكون عينة التعليمات البرمجية من المكونات التالية. أضف هذه المكونات من عينة تطبيق Android إلى تطبيقك الخاص.

المكون النوع Source ‏‏الوصف
B2CUser الدرجة KotlinJava يمثل مستخدم متاجرة عمل-مستهلك. تسمح هذه الفئة للمستخدمين بتسجيل الدخول باستخدام سياسات متعددة.
B2CModeFragment فئة الجزء KotlinJava يمثل الجزء جزءًا معياريًا من تسجيل الدخول باستخدام واجهة مستخدم AAD (دليل Azure النشط) متاجرة عمل-مستهلك ضمن نشاطك الرئيسي. يحتوي هذا الجزء على معظم تعليمة برمجية المصادقة.
fragment_b2c_mode.xml تخطيط جزء KotlinJava يحدد بنية واجهة مستخدم لمكون جزء B2CModeFragment.
B2C التكوين الدرجة KotlinJava يحتوي ملف التكوين على معلومات حول موفر هوية AAD (دليل Azure النشط) متاجرة عمل-مستهلك الخاص بك. يستخدم تطبيق الأجهزة المحمولة هذه المعلومات لإنشاء علاقة ثقة مع Azure AD B2C، وتسجيل دخول المستخدمين وخروجهم، والحصول على الرموز المميزة، والتحقق من صحتها. لمزيد من إعدادات التكوين، راجع ملف auth_config_b2c.json.
auth_config_b2c.json ملف JSON KotlinJava يحتوي ملف التكوين على معلومات حول موفر هوية AAD (دليل Azure النشط) متاجرة عمل-مستهلك الخاص بك. يستخدم تطبيق الأجهزة المحمولة هذه المعلومات لإنشاء علاقة ثقة مع Azure AD B2C، وتسجيل دخول المستخدمين وخروجهم، والحصول على الرموز المميزة، والتحقق من صحتها. لمزيد من إعدادات التكوين، راجع فئة تكوين B2C.

الخطوة 3: تكوين تطبيق Android الخاص بك

بعد إضافة مكونات المصادقة، قم بتكوين تطبيق Android باستخدام إعدادات AAD (دليل Azure النشط) متاجرة عمل-مستهلك. تم تكوين إعدادات موفر هويةAAD (دليل Azure النشط) متاجرة عمل-مستهلك في ملف auth_config_b2c.json وفئة B2CConfiguration.

للحصول على إرشادات، ارجع إلى تكوين نموذج تطبيق الجوال.

الخطوة 4: قم بتعيين عنوان URI لإعادة التوجيه

قم بتكوين المكان الذي يستمع فيه تطبيقك إلى استجابة الرمز المميز AAD (دليل Azure النشط) متاجرة عمل-مستهلك.

  1. إنشاء تجزئة توقيع تطوير جديدة. سيتغير هذا لكل بيئة تطوير.

    لـ Windows:

    keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%\.android\debug.keystore | openssl sha1 -binary | openssl base64
    

    بالنسبة إلى iOS:

    keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
    

    بالنسبة لبيئة الإنتاج، استخدم الأمر التالي:

    keytool -exportcert -alias SIGNATURE_ALIAS -keystore PATH_TO_KEYSTORE | openssl sha1 -binary | openssl base64
    

    لمزيد من المساعدة في توقيع تطبيقاتك، راجع تسجيل تطبيق Android.

  2. في app>src>main>AndroidManifest.xml، أضف النشاط BrowserTabActivity أدناه إلى نص التطبيق:

    <!--Intent filter to capture System Browser or Authenticator calling back to our app after sign-in-->
    <activity
        android:name="com.microsoft.identity.client.BrowserTabActivity">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="msauth"
                android:host="Package_Name"
                android:path="/Signature_Hash" />
        </intent-filter>
    </activity>
    
  3. استبدلها بـ Signature_Hashالتجزئة التي أنشأتها.

  4. استبدل Package_Name باسم حزمة Android الخاص بك.

لتحديث تسجيل تطبيق الأجهزة المحمولة باستخدام عنوان URI لإعادة توجيه التطبيق الخاص بك، قم بما يلي:

  1. سجل الدخول إلى مدخل Azure.
  2. إذا كان لديك حق الوصول إلى عدة مستأجرين، فحدد رمز الإعدادات في القائمة العلوية للتبديل إلى مستأجر Azure AD B2C من قائمة Directories + subscriptions.
  3. ابحث عن Azure AD B2C وحدده.
  4. حدد App registrations، ثم حدد التطبيق الذي قمت بتسجيله فيStep 2.3: Register the mobile app.
  5. تحديد المصادقة
  6. ضمن Android، حدد Add URI.
  7. أدخل Package nameوSignature hash.
  8. حدد حفظ.

يجب أن يبدو عنوان URIBrowserTabActivity لإعادة التوجيه والنشاط مشابهًا للعينة التالية:

يبدو عنوان URL لإعادة التوجيه لعينة Android على النحو التالي:

msauth://com.azuresamples.msalandroidkotlinapp/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D

يستخدم عامل تصفية الهدف نفس النمط، كما هو موضح في مقتطف XML التالي:

<activity android:name="com.microsoft.identity.client.BrowserTabActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:host="com.azuresamples.msalandroidkotlinapp"
            android:path="/1wIqXSqBj7w+h11ZifsnqwgyKrY="
            android:scheme="msauth" />
    </intent-filter>
</activity>

الخطوة 5: قم بتخصيص الكتل البرمجية الإنشائية الخاصة بك

يصف هذا القسم الكتل البرمجية الإنشائية التي تمكّن المصادقة لتطبيق Android الخاص بك. يسرد الجدول التالي أساليب B2CModeFragment وكيفية تخصيص التعليمات البرمجية الخاصة بك.

الخطوة 5.1: إنشاء مثيل لتطبيق عميل عام

تطبيقات العميل العامة غير موثوق بها للحفاظ على أسرار التطبيق بأمان، وليس لديها أسرار العميل. في onCreate أو onCreateView، قم بإنشاء مثيل MSAL باستخدام عنصر تطبيق العميل العام متعدد الحسابات.

MultipleAccountPublicClientApplicationيتم استخدام الفصل لإنشاء تطبيقات تستند إلى MSAL والتي تسمح بتسجيل الدخول إلى حسابات متعددة في نفس الوقت. تسمح الفئة بتسجيل الدخول باستخدام تدفقات مستخدم AAD (دليل Azure النشط) متاجرة عمل-مستهلك المتعددة أو نُهج مخصصة. على سبيل المثال، يقوم المستخدمون بتسجيل الدخول من خلال تدفق مستخدم الاشتراك أو تسجيل الدخول وبعد ذلك، يقومون بتشغيل تدفق مستخدمتعديل الملف التعريف.

يوضح مقتطف الشفرة التالي كيفية بدء مكتبة MSAL auth_config_b2c.jsonبملف التكوين JSON.

PublicClientApplication.createMultipleAccountPublicClientApplication(context!!,
    R.raw.auth_config_b2c,
    object : IMultipleAccountApplicationCreatedListener {
        override fun onCreated(application: IMultipleAccountPublicClientApplication) {
            // Set the MultipleAccountPublicClientApplication to the class member b2cApp
            b2cApp = application
            // Load the account (if there is any)
            loadAccounts()
        }

        override fun onError(exception: MsalException) {
            // Error handling
            displayError(exception)
        }
    })

الخطوة 5.2: تحميل الحسابات

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

يوضح مقتطف الشفرة التالي كيفية تحميل الحسابات.

private fun loadAccounts() {
    if (b2cApp == null) {
        return
    }
    b2cApp!!.getAccounts(object : LoadAccountsCallback {
        override fun onTaskCompleted(result: List<IAccount>) {
            users = B2CUser.getB2CUsersFromAccountList(result)
            updateUI(users)
        }
    
        override fun onError(exception: MsalException) {
            displayError(exception)
        }
    })
    }

الخطوة 5.3: ابدأ طلب تخويل تفاعلي

طلب التخويل التفاعلي هو تدفق يُطلب من المستخدمين فيه التسجيل أو تسجيل الدخول. initializeUIيعمل الأسلوب runUserFlowButton على تكوين حدث النقر. عندما يحدد المستخدمون زر Run User Flow، يأخذهم التطبيق إلى AAD (دليل Azure النشط) متاجرة عمل-مستهلك لإكمال تدفق تسجيل الدخول.

تقوم runUserFlowButton.setOnClickListenerالطريقة بتجهيزAcquireTokenParameters العنصر بالبيانات ذات الصلة بطلب التخويل. acquireTokenثم يطالب الأسلوب المستخدمين بإكمال تدفق التسجيل أو تسجيل الدخول.

توضح القصاصة البرمجية التالية كيفية بدء طلب التفويض التفاعلي:

val parameters = AcquireTokenParameters.Builder()
        .startAuthorizationFromActivity(activity)
        .fromAuthority(getAuthorityFromPolicyName(policy_list.getSelectedItem().toString()))
        .withScopes(B2CConfiguration.scopes)
        .withPrompt(Prompt.LOGIN)
        .withCallback(authInteractiveCallback)
        .build()

b2cApp!!.acquireToken(parameters)

الخطوة 5.4: قم بإجراء طلب تخويل تفاعلي لمعاودة الاتصال

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

يقوم أسلوب رد الاتصال AuthenticationResultبتمرير العنصر أو رسالة خطأ فيMsalException العنصر. استخدم هذا الأسلوب من أجل:

  • قم بتحديث واجهة مستخدم تطبيق الأجهزة المحمولة بالمعلومات بعد انتهاء تسجيل الدخول.
  • إعادة تحميل عنصر الحسابات.
  • استدعي خدمة واجهة برمجة تطبيقات الويب باستخدام الرمز المميز للوصول.
  • معالجة أخطاء المصادقة.

توضح قصاصة برمجية التالي استخدام رد اتصال المصادقة التفاعلية.

private val authInteractiveCallback: AuthenticationCallback
    private get() = object : AuthenticationCallback {
        override fun onSuccess(authenticationResult: IAuthenticationResult) {
            /* Successfully got a token, use it to call a protected resource; web API  */
            Log.d(TAG, "Successfully authenticated")

            /* display result info */
            displayResult(authenticationResult)

            /* Reload account asynchronously to get the up-to-date list. */
            loadAccounts()
        }

        override fun onError(exception: MsalException) {
            val B2C_PASSWORD_CHANGE = "AADB2C90118"
            if (exception.message!!.contains(B2C_PASSWORD_CHANGE)) {
                txt_log!!.text = """
                    Users click the 'Forgot Password' link in a sign-up or sign-in user flow.
                    Your application needs to handle this error code by running a specific user flow that resets the password.
                    """.trimIndent()
                return
            }

            /* Failed to acquireToken */Log.d(TAG, "Authentication failed: $exception")
            displayError(exception)
            if (exception is MsalClientException) {
                /* Exception inside MSAL, more info inside MsalError.java */
            } else if (exception is MsalServiceException) {
                /* Exception when communicating with the STS, likely config issue */
            }
        }

        override fun onCancel() {
            /* User canceled the authentication */
            Log.d(TAG, "User cancelled login.")
        }
    }

الخطوة 6: اتصل بواجهة برمجة تطبيقات الويب

لاستدعاء واجهة برمجة تطبيقات ويب للتخويل المستندة إلى الرمز المميز، يحتاج التطبيق إلى رمز وصول صالح. يقوم التطبيق بما يلي:

  1. يكتسب رمز وصول من خلال الأذونات (النطاقات) المطلوبة لنقطة نهاية واجهة برمجة تطبيقات الويب.
  2. يُدخل رمز الوصول كرمز مميز للحامل في عنوان التفويض لطلب HTTP باستخدام هذا التنسيق:
Authorization: Bearer <access-token>

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

قبل استدعاء واجهة برمجة تطبيقات الويب، استدعacquireTokenSilentAsync الطريقة بالنطاقات المناسبة لنقطة نهاية واجهة برمجة تطبيقات الويب. تقوم مكتبة MSAL بما يلي:

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

توضح القصاصة البرمجية التالية كيفية الحصول على الرمز المميز للوصول:

acquireTokenSilentButtonيكتسب حدث النقر على الزر رمز وصول بالنطاقات المتوفرة.

btn_acquireTokenSilently.setOnClickListener(View.OnClickListener {
    if (b2cApp == null) {
        return@OnClickListener
    }
    val selectedUser = users!![user_list.getSelectedItemPosition()]
    selectedUser.acquireTokenSilentAsync(b2cApp!!,
            policy_list.getSelectedItem().toString(),
            B2CConfiguration.scopes,
            authSilentCallback)
})

authSilentCallbackتقوم طريقة رد الاتصال بإرجاع رمز وصول واستدعاء واجهة برمجة تطبيقات الويب:

private val authSilentCallback: SilentAuthenticationCallback
    private get() = object : SilentAuthenticationCallback {
        override fun onSuccess(authenticationResult: IAuthenticationResult) {
            Log.d(TAG, "Successfully authenticated")

            /* Call your web API here*/
            callWebAPI(authenticationResult)
        }

        override fun onError(exception: MsalException) {
            /* Failed to acquireToken */
            Log.d(TAG, "Authentication failed: $exception")
            displayError(exception)
            if (exception is MsalClientException) {
                /* Exception inside MSAL, more info inside MsalError.java */
            } else if (exception is MsalServiceException) {
                /* Exception when communicating with the STS, likely config issue */
            } else if (exception is MsalUiRequiredException) {
                /* Tokens expired or no session, retry with interactive */
            }
        }
    }

يوضح المثال التالي كيفية استدعاء واجهة برمجة تطبيقات الويب المحمية برمز لحاملها:

@Throws(java.lang.Exception::class)
private fun callWebAPI(authenticationResult: IAuthenticationResult) {
    val accessToken = authenticationResult.accessToken
    val thread = Thread {
        try {
            val url = URL("https://your-app-service.azurewebsites.net/helo")
            val conn = url.openConnection() as HttpsURLConnection
            conn.setRequestProperty("Accept", "application/json")
            
            // Set the bearer token
            conn.setRequestProperty("Authorization", "Bearer $accessToken")
            if (conn.responseCode == HttpURLConnection.HTTP_OK) {
                val br = BufferedReader(InputStreamReader(conn.inputStream))
                var strCurrentLine: String?
                while (br.readLine().also { strCurrentLine = it } != null) {
                    Log.d(TAG, strCurrentLine)
                }
            }
            conn.disconnect()
        } catch (e: IOException) {
            e.printStackTrace()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
    thread.start()
}

أضف إذنًا لإجراء عمليات الشبكة

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

<uses-permission android:name="android.permission.INTERNET"/>

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

تعلم كيف: