المراجعة لعام 2024، الربع الرابع: التعرّف على كيفية تبسيط مسارات المصادقة باستخدام واجهة برمجة التطبيقات Credential Manager API في تطبيق Android

1. قبل البدء

تطرح حلول المصادقة التقليدية عددًا من تحديات الأمان وسهولة الاستخدام.

يتم استخدام كلمات المرور على نطاق واسع، ولكن...

  • من السهل نسيانها
  • يحتاج المستخدمون إلى المعرفة لإنشاء كلمات مرور قوية.
  • من السهل على المهاجمين خداع المستخدمين وجمع بياناتهم وإعادة تشغيلها.

عمل فريق Android على إنشاء واجهة برمجة التطبيقات Credential Manager API لتبسيط تجربة تسجيل الدخول ومعالجة مخاطر الأمان من خلال إتاحة مفاتيح المرور، وهي الجيل التالي من معايير المجال لـ المصادقة بدون كلمة مرور.

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

سيتمكّن المستخدمون من إنشاء مفاتيح مرور وتخزينها في "مدير كلمات المرور في Google"، ما يؤدي إلى مزامنة مفاتيح المرور هذه على جميع أجهزة Android التي سجّل المستخدم الدخول إليها. يجب إنشاء مفتاح مرور وربطه بحساب مستخدم وتخزين المفتاح العام له على خادم قبل أن يتمكّن المستخدم من تسجيل الدخول باستخدامه.

في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية الاشتراك باستخدام مفاتيح المرور وكلمة المرور باستخدام Credential Manager API واستخدامها لأغراض المصادقة في المستقبل. هناك عمليتان تتضمّنان ما يلي:

  • الاشتراك : باستخدام مفاتيح المرور وكلمة المرور
  • تسجيل الدخول : باستخدام مفاتيح المرور وكلمة المرور المحفوظة

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

  • فهم أساسي لكيفية تشغيل التطبيقات في "استوديو Android"
  • فهم أساسي لمسار المصادقة في تطبيقات Android
  • فهم أساسي لمفاتيح المرور

المُعطيات

  • كيفية إنشاء مفتاح مرور
  • كيفية حفظ كلمة المرور في مدير كلمات المرور
  • كيفية مصادقة المستخدمين باستخدام مفتاح مرور أو كلمة مرور محفوظة

المتطلبات

إحدى مجموعات الأجهزة التالية:

  • جهاز Android يعمل بالإصدار 9 أو إصدار أحدث (للمفاتيح المميّزة) والإصدار 4.4 أو إصدار أحدث(لمصادقة كلمة المرور من خلال واجهة برمجة التطبيقات Credential Manager API)
  • الجهاز المزوّد بجهاز استشعار حيوي
  • احرص على تسجيل مقياس حيوي (أو قفل شاشة).
  • إصدار المكوِّن الإضافي Kotlin : 1.8.10

2. الإعداد

  1. يمكنك استنساخ هذا المستودع على الكمبيوتر المحمول من فرع credman_codelab : https://github.com/android/identity-samples/tree/credman_codelab
git clone -b credman_codelab https://github.com/android/identity-samples.git
  1. انتقِل إلى وحدة CredentialManager وافتح المشروع في Android Studio.

لنطّلِع على الحالة الأولية للتطبيق

لمعرفة كيفية عمل الحالة الأولية للتطبيق، اتّبِع الخطوات التالية:

  1. افتح التطبيق.
  2. ستظهر لك شاشة رئيسية تتضمّن زرَّي الاشتراك وتسجيل الدخول. لا تؤدي هذه الأزرار أيّ وظيفة إلى الآن، ولكن سنفعّل وظائفها في الأقسام القادمة.

7a6fe80f4cf877a8.jpeg

3- إضافة إمكانية الاشتراك باستخدام مفاتيح المرور

عند الاشتراك في حساب جديد على تطبيق Android يستخدم واجهة برمجة التطبيقات Credential Manager API، يمكن للمستخدمين إنشاء مفتاح مرور لحساباتهم. سيتم تخزين مفتاح المرور هذا بأمان في مقدّم بيانات الاعتماد الذي يختاره المستخدم، وسيتم استخدامه لعمليات تسجيل الدخول المستقبلية، بدون أن يُطلب من المستخدم إدخال كلمة المرور في كل مرة.

الآن، عليك إنشاء مفتاح مرور وتسجيل بيانات اعتماد المستخدم باستخدام المقاييس الحيوية أو قفل الشاشة.

الاشتراك باستخدام مفتاح مرور

يحدِّد الرمز البرمجي داخل Credential Manager/app/main/java/SignUpFragment.kt حقل نصي "اسم المستخدم" وزرًا للاشتراك باستخدام مفتاح مرور.

1f4c50daa2551f1.jpeg

تمرير التحدي واستجابة json الأخرى إلى طلب createPasskey()

قبل إنشاء مفتاح مرور، عليك طلب المعلومات اللازمة من الخادم لنقلها إلى واجهة برمجة التطبيقات Credential Manager API أثناء طلب createCredential().

لديك حاليًا استجابة وهمية في مواد عرض مشروعك، تُسمى RegFromServer.txt، والتي تعرض المَعلمات اللازمة في هذا الدليل التعليمي حول الرموز البرمجية.

  • في تطبيقك، انتقِل إلى SignUpFragment.kt، وابحث عن الطريقة signUpWithPasskeys التي ستكتب فيها منطق إنشاء مفتاح مرور والسماح للمستخدم بالدخول. يمكنك العثور على الطريقة في الصف نفسه.
  • تحقّق من مجموعة else باستخدام تعليق لاستدعاء createPasskey() واستبدِلها بالرمز البرمجي التالي:

SignUpFragment.kt

//TODO : Call createPasskey() to signup with passkey

val data = createPasskey()

سيتم استدعاء هذه الطريقة بعد ملء اسم مستخدم صالح على الشاشة.

  • داخل طريقة createPasskey()، عليك إنشاء CreatePublicKeyCredentialRequest() مع عرض المَعلمات اللازمة.

SignUpFragment.kt

//TODO create a CreatePublicKeyCredentialRequest() with necessary registration json from server

val request = CreatePublicKeyCredentialRequest(fetchRegistrationJsonFromServer())

تقرأ طريقة fetchRegistrationJsonFromServer() استجابة JSON PublicKeyCredentialCreationOptions لخادم محاكي من مواد العرض وتُعيد ملف JSON للتسجيل ليتم تمريره أثناء إنشاء مفتاح المرور.

  • ابحث عن الطريقة fetchRegistrationJsonFromServer() واستبدِل TODO بالرمز التالي لعرض JSON وأزِل أيضًا بيان عرض السلسلة الفارغة :

SignUpFragment.kt

//TODO fetch registration mock response

val response = requireContext().readFromAsset("RegFromServer")

//Update userId,challenge, name and Display name in the mock
return response.replace("<userId>", getEncodedUserId())
   .replace("<userName>", binding.username.text.toString())
   .replace("<userDisplayName>", binding.username.text.toString())
   .replace("<challenge>", getEncodedChallenge())
  • ملف JSON هذا غير مكتمل ويحتوي على 4 حقول يجب استبدالها.
  • يجب أن يكون UserId فريدًا حتى يتمكّن المستخدم من إنشاء مفاتيح مرور متعددة (إذا لزم الأمر). استبدِل <userId> بالقيمة userId التي تم إنشاؤها.
  • يجب أن يكون <challenge> فريدًا أيضًا حتى تتمكّن من إنشاء تحدّي فريد عشوائي. الطريقة متوفّرة في الرمز البرمجي.

قد يعرض ردّ الخادم الفعلي PublicKeyCredentialCreationOptions المزيد من الخيارات. في ما يلي مثال على بعض هذه الحقول:

{
  "challenge": String,
  "rp": {
    "name": String,
    "id": String
  },
  "user": {
    "id": String,
    "name": String,
    "displayName": String
  },
  "pubKeyCredParams": [
    {
      "type": "public-key",
      "alg": -7
    },
    {
      "type": "public-key",
      "alg": -257
    }
  ],
  "timeout": 1800000,
  "attestation": "none",
  "excludeCredentials": [],
  "authenticatorSelection": {
    "authenticatorAttachment": "platform",
    "requireResidentKey": true,
    "residentKey": "required",
    "userVerification": "required"
  }
}

يوضّح الجدول التالي بعض المَعلمات المهمة في عنصر PublicKeyCredentialCreationOptions:

المعلّمات

الأوصاف

challenge

سلسلة عشوائية ينشئها الخادم تحتوي على قدر كافٍ من التشويش يجعل تخمينها غير ممكن. يجب ألا يقلّ طولها عن 16 بايت. هذا الحقل مطلوب، ولكن لا يتم استخدامه أثناء التسجيل ما لم يتم إجراء إقرار.

user.id

المعرّف الفريد للمستخدم يجب ألا تتضمّن هذه القيمة معلومات تحدّد الهوية الشخصية، مثل عناوين البريد الإلكتروني أو أسماء المستخدمين. وستعمل بشكل جيد قيمة عشوائية تبلغ 16 بايت يتم إنشاؤها لكل حساب.

user.name

يجب أن يحتوي هذا الحقل على معرّف فريد للحساب يمكن للمستخدم التعرّف عليه، مثل عنوان بريده الإلكتروني أو اسمه. سيتم عرض هذا في أداة اختيار الحسابات. (في حال استخدام اسم مستخدم، استخدِم القيمة نفسها المستخدَمة في مصادقة كلمة المرور).

user.displayName

هذا الحقل هو اسم اختياري وأكثر سهولة للاستخدام للحساب.

rp.id

يتوافق كيان الطرف المعنيّ بالاعتماد مع تفاصيل طلبك. وتتضمّن السمات التالية:

  • name (مطلوب): اسم تطبيقك
  • ID (اختياري): يتوافق مع النطاق أو النطاق الفرعي. وفي حال عدم توفّره، يتم استخدام النطاق الحالي.
  • icon (اختياري)

pubKeyCredParams

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

excludeCredentials

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

authenticatorSelection.authenticatorAttachment

يشير إلى ما إذا كان يجب إرفاق الجهاز بالنظام الأساسي أو لا أو ما إذا لم يكن هناك شرط لذلك. اضبط هذه القيمة على platform. يشير ذلك إلى أنّك تريد مصادقة مضمّنة في جهاز المنصة، ولن يُطلب من المستخدم إدخال مفتاح أمان USB مثلاً.

residentKey

حدِّد القيمة required لإنشاء مفتاح مرور.

إنشاء بيانات اعتماد

  1. بعد إنشاء CreatePublicKeyCredentialRequest()، عليك الاتصال برقم createCredential() وإرسال الطلب الذي تم إنشاؤه.

SignUpFragment.kt

//TODO call createCredential() with createPublicKeyCredentialRequest

try {
   response = credentialManager.createCredential(
       requireActivity(),
       request
   ) as CreatePublicKeyCredentialResponse
} catch (e: CreateCredentialException) {
   configureProgress(View.INVISIBLE)
   handlePasskeyFailure(e)
}
  • تُرسل المعلومات المطلوبة إلى createCredential().
  • بعد نجاح الطلب، ستظهر لك شاشة سفلية على الشاشة تطلب منك إنشاء مفتاح مرور.
  • يمكن للمستخدمين الآن إثبات هويتهم من خلال المقاييس الحيوية أو قفل الشاشة وما إلى ذلك.
  • يمكنك التعامل مع مستوى ظهور العروض المعروضة والتعامل مع الاستثناءات في حال تعذّر الطلب أو عدم نجاحه لأي سبب. يتم تسجيل رسائل الخطأ هنا وعرضها على التطبيق في مربّع حوار الخطأ. يمكنك الاطّلاع على سجلّات الأخطاء الكاملة من خلال Android Studio أو باستخدام الأمر adb debug.

1ea8ace66135de1e.png

  1. أخيرًا، عليك إكمال عملية التسجيل. يُرسِل التطبيق بيانات اعتماد المفتاح العام إلى الخادم الذي يسجِّلها للمستخدم الحالي.

لقد استخدمنا هنا خادمًا وهميًا، لذا نعرض فقط القيمة true للإشارة إلى أنّ الخادم قد حفظ المفتاح العام المسجَّل لأغراض المصادقة والتحقّق في المستقبل. يمكنك الاطّلاع على مزيد من المعلومات حول تسجيل مفاتيح المرور من جهة الخادم لتنفيذ ذلك بنفسك.

داخل طريقة signUpWithPasskeys()، ابحث عن التعليق ذي الصلة واستبدِله بالرمز البرمجي التالي:

SignUpFragment.kt

//TODO : complete the registration process after sending public key credential to your server and let the user in

data?.let {
   registerResponse()
   DataProvider.setSignedInThroughPasskeys(true)
   listener.showHome()
}
  • يعرض registerResponse() القيمة true، ما يشير إلى أنّ الخادم النموذجي قد حفظ المفتاح العام لاستخدامه في المستقبل.
  • اضبط علامة setSignedInThroughPasskeys على true.
  • بعد تسجيل الدخول، يمكنك إعادة توجيه المستخدم إلى الشاشة الرئيسية.

قد يحتوي PublicKeyCredential الحقيقي على المزيد من الحقول. في ما يلي مثال على هذه الحقول:

{
  "id": String,
  "rawId": String,
  "type": "public-key",
  "response": {
    "clientDataJSON": String,
    "attestationObject": String,
  }
}

يوضّح الجدول التالي بعض المَعلمات المهمة في عنصر PublicKeyCredential:

المعلّمات

الأوصاف

id

معرّف مُشفَّر بترميز Base64URL لمفتاح المرور الذي تم إنشاؤه يساعد رقم التعريف هذا المتصفّح في تحديد ما إذا كان هناك مفتاح مرور مطابق في الجهاز عند المصادقة. يجب تخزين هذه القيمة في قاعدة البيانات في الخلفية.

rawId

نسخة من ArrayBuffer لتعريف بيانات الاعتماد

response.clientDataJSON

بيانات العميل المشفّرة في عنصر ArrayBuffer

response.attestationObject

عنصر شهادة مُشفَّر بتنسيق ArrayBuffer يحتوي على معلومات مهمة، مثل رقم تعريف موفِّر خدمات الربط والعلامات والمفتاح العام.

شغِّل التطبيق، وسيكون بإمكانك النقر على الزر الاشتراك باستخدام مفاتيح المرور وإنشاء مفتاح مرور.

4. حفظ كلمة مرور في "موفِّر بيانات الاعتماد"

في هذا التطبيق، داخل شاشة "الاشتراك"، سبق أن تم تنفيذ ميزة الاشتراك باستخدام اسم المستخدم وكلمة المرور لأغراض توضيحية.

لحفظ بيانات اعتماد كلمة مرور المستخدم مع مقدّم كلمة المرور، عليك تنفيذ CreatePasswordRequest لنقلها إلى createCredential() لحفظ كلمة المرور.

  • ابحث عن طريقة signUpWithPassword()، واستبدِل TODO باستدعاء createPassword:

SignUpFragment.kt

//TODO : Save the user credential password with their password provider

createPassword()
  • داخل الطريقة createPassword()، عليك إنشاء طلب كلمة مرور على النحو التالي، واستبدال TODO بالرمز البرمجي التالي:

SignUpFragment.kt

//TODO : CreatePasswordRequest with entered username and password

val request = CreatePasswordRequest(
   binding.username.text.toString(),
   binding.password.text.toString()
)
  • بعد ذلك، ضمن طريقة createPassword()، أنشئ بيانات اعتماد باستخدام طلب إنشاء كلمة مرور واحفظ بيانات اعتماد كلمة مرور المستخدم مع موفّر كلمة المرور. استبدِل TODO بالرمز التالي:

SignUpFragment.kt

//TODO : Create credential with created password request


try {
   credentialManager.createCredential(requireActivity(), request) as CreatePasswordResponse
} catch (e: Exception) {
   Log.e("Auth", " Exception Message : " + e.message)
}
  • لقد نجحت الآن في حفظ بيانات اعتماد كلمة المرور مع مقدّم كلمة مرور المستخدم للمصادقة باستخدام كلمة مرور بنقرة واحدة فقط.

5- إضافة إمكانية المصادقة باستخدام مفتاح مرور أو كلمة مرور

يمكنك الآن استخدامها كطريقة للمصادقة على تطبيقك بأمان.

76e81460b26f9798.png

الحصول على التحدي والخيارات الأخرى لتمرير طلب getPasskey()

قبل أن تطلب من المستخدم المصادقة، عليك طلب مَعلمات لتمرير WebAuthn JSON من الخادم، بما في ذلك طلب التحقّق.

لديك ردّ وهمي في مواد العرض (AuthFromServer.txt) يعرض هذه المَعلمات في هذا الدليل التعليمي.

  • في تطبيقك، انتقِل إلى SignInFragment.kt، وابحث عن الطريقة signInWithSavedCredentials التي ستكتب فيها منطق المصادقة من خلال مفتاح المرور أو كلمة المرور المحفوظة، ثم اسمح للمستخدم بالدخول:
  • تحقّق من مجموعة else باستخدام تعليق لاستدعاء createPasskey() واستبدِلها بالرمز البرمجي التالي:

SignInFragment.kt

//TODO : Call getSavedCredentials() method to signin using passkey/password

val data = getSavedCredentials()
  • داخل الطريقة getSavedCredentials()‎، عليك إنشاء GetPublicKeyCredentialOption() بالمَعلمات اللازمة للحصول على بيانات الاعتماد من مقدّم بيانات الاعتماد.

SigninFragment.kt

//TODO create a GetPublicKeyCredentialOption() with necessary registration json from server

val getPublicKeyCredentialOption =
   GetPublicKeyCredentialOption(fetchAuthJsonFromServer(), null)

تقرأ طريقة fetchAuthJsonFromServer() استجابة JSON للمصادقة من مواد العرض وتُعيد JSON للمصادقة لاسترداد جميع مفاتيح المرور المرتبطة بحساب المستخدم هذا.

المَعلمة الثانية لدالة GetPublicKeyCredentialOption() هي clientDataHash، وهي تشير إلى تجزئة تُستخدَم للتحقّق من هوية الطرف الموثوق به. لا تضبط هذا الخيار إلّا إذا كنت قد ضبطت GetCredentialRequest.origin. بالنسبة إلى نموذج التطبيق، يتم ضبط هذا الخيار على null.

  • ابحث عن الطريقة fetchAuthJsonFromServer() واستبدِل TODO بالرمز البرمجي التالي لعرض json وأزِل أيضًا بيان عرض السلسلة الفارغة:

SignInFragment.kt

//TODO fetch authentication mock json

return requireContext().readFromAsset("AuthFromServer")

ملاحظة : تم تصميم خادم هذا الدليل التعليمي لعرض ملف JSON مشابه قدر الإمكان لقائمة PublicKeyCredentialRequestOptions التي يتم تمريرها إلى طلب getCredential() في واجهة برمجة التطبيقات. يتضمّن مقتطف الرمز البرمجي التالي بعض الأمثلة على الخيارات التي قد تتلقّاها في ردّ حقيقي:

{
  "challenge": String,
  "rpId": String,
  "userVerification": "",
  "timeout": 1800000
}

يوضّح الجدول التالي بعض المَعلمات المهمة في عنصر PublicKeyCredentialRequestOptions:

المعلّمات

الأوصاف

challenge

تحدٍّ ينشئه الخادم في عنصر ArrayBuffer هذا الإجراء مطلوب لمنع هجمات إعادة التشغيل. لا تقبل أبدًا التحدي نفسه في ردّ مرتين. يمكنك اعتباره رمز CSRF المميَّز.

rpId

رقم تعريف مقدّم الخدمة هو نطاق. يمكن للموقع الإلكتروني تحديد نطاقه أو لاحقة قابلة للتسجيل. يجب أن تتطابق هذه القيمة مع المَعلمة rp.id المستخدَمة عند إنشاء مفتاح المرور.

  • بعد ذلك، عليك إنشاء عنصر PasswordOption() لاسترداد جميع كلمات المرور المحفوظة في موفِّر كلمات المرور من خلال واجهة برمجة التطبيقات Credential Manager API لحساب المستخدم هذا. داخل طريقة getSavedCredentials()، ابحث عن TODO واستبدِله بما يلي:

SigninFragment.kt

//TODO create a PasswordOption to retrieve all the associated user's password

val getPasswordOption = GetPasswordOption()

الحصول على بيانات الاعتماد

  • بعد ذلك، عليك الاتصال بفريق getCredential() لطلب جميع الخيارات أعلاه لاسترداد بيانات الاعتماد المرتبطة:

SignInFragment.kt

//TODO call getCredential() with required credential options

val result = try {
   credentialManager.getCredential(
       requireActivity(),
       GetCredentialRequest(
           listOf(
               getPublicKeyCredentialOption,
               getPasswordOption
           )
     )
   )
} catch (e: Exception) {
   configureViews(View.INVISIBLE, true)
   Log.e("Auth", "getCredential failed with exception: " + e.message.toString())
   activity?.showErrorAlert(
       "An error occurred while authenticating through saved credentials. Check logs for additional details"
   )
   return null
}

if (result.credential is PublicKeyCredential) {
   val cred = result.credential as PublicKeyCredential
   DataProvider.setSignedInThroughPasskeys(true)
   return "Passkey: ${cred.authenticationResponseJson}"
}
if (result.credential is PasswordCredential) {
   val cred = result.credential as PasswordCredential
   DataProvider.setSignedInThroughPasskeys(false)
   return "Got Password - User:${cred.id} Password: ${cred.password}"
}
if (result.credential is CustomCredential) {
   //If you are also using any external sign-in libraries, parse them here with the utility functions provided.
}

  • تُرسل المعلومات المطلوبة إلى getCredential(). يأخذ هذا الإجراء قائمة خيارات بيانات الاعتماد وسياق النشاط لعرض الخيارات في اللوحة السفلية في هذا السياق.
  • بعد نجاح الطلب، ستظهر لك لوحة سفلية على الشاشة تعرض جميع بيانات الاعتماد التي تم إنشاؤها للحساب المرتبط.
  • يمكن للمستخدمين الآن إثبات هويتهم من خلال المقاييس الحيوية أو قفل الشاشة وما إلى ذلك لمصادقة بيانات الاعتماد التي تم اختيارها.
  • إذا كانت بيانات الاعتماد التي تم اختيارها هي PublicKeyCredential، اضبط العلامة setSignedInThroughPasskeys على true. ويمكنك بدلاً من ذلك ضبطها على false.

يتضمّن مقتطف الرمز البرمجي التالي مثالاً على عنصر PublicKeyCredential:

{
  "id": String
  "rawId": String
  "type": "public-key",
  "response": {
    "clientDataJSON": String
    "authenticatorData": String
    "signature": String
    "userHandle": String
  }
}

الجدول التالي ليس شاملاً، ولكنه يحتوي على المَعلمات المهمة في عنصر PublicKeyCredential:

المعلّمات

الأوصاف

id

رقم التعريف المشفَّر بترميز Base64URL لمستند اعتماد مفتاح المرور الذي تم إثبات صحته

rawId

نسخة من ArrayBuffer لتعريف بيانات الاعتماد

response.clientDataJSON

عنصر ArrayBuffer لبيانات العميل يحتوي هذا الحقل على معلومات، مثل الطلب والمصدر الذي يحتاج خادم RP إلى التحقّق منه.

response.authenticatorData

عنصر ArrayBuffer لبيانات معرّف الهوية يحتوي هذا الحقل على معلومات مثل رقم تعريف موفِّر المحتوى.

response.signature

عنصر ArrayBuffer للتوقيع هذه القيمة هي جوهر بيانات الاعتماد ويجب إثبات صحتها على الخادم.

response.userHandle

عنصر ArrayBuffer يحتوي على رقم تعريف المستخدم الذي تم ضبطه في وقت الإنشاء يمكن استخدام هذه القيمة بدلاً من معرّف بيانات الاعتماد إذا كان الخادم بحاجة إلى اختيار قيم المعرّفات التي يستخدمها، أو إذا أرادت الخلفية تجنُّب إنشاء فهرس بمعرّفات بيانات الاعتماد.

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

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

داخل الطريقة signInWithSavedCredentials()، ابحث عن التعليق ذي الصلة واستبدِله بالرمز البرمجي التالي:

SignInFragment.kt

//TODO : complete the authentication process after validating the public key credential to your server and let the user in.

data?.let {
   sendSignInResponseToServer()
   listener.showHome()
}
  • يعرض sendSigninResponseToServer() القيمة true (صحيح) للإشارة إلى أنّ الخادم (المزيف) قد تحقّق من المفتاح العام لاستخدامه في المستقبل.
  • بعد تسجيل الدخول، يمكنك إعادة توجيه المستخدم إلى الشاشة الرئيسية.

شغِّل التطبيق وانتقِل إلى تسجيل الدخول > تسجيل الدخول باستخدام مفاتيح المرور/كلمة المرور المحفوظة، وجرِّب تسجيل الدخول باستخدام بيانات الاعتماد المحفوظة.

تجربة الميزة

نفَّذت عملية إنشاء مفاتيح المرور وحفظ كلمة المرور في "مدير بيانات الاعتماد" والمصادقة من خلال مفاتيح المرور أو كلمة المرور المحفوظة باستخدام واجهة برمجة التطبيقات Credential Manager API في تطبيق Android.

6- تهانينا!

لقد أكملت هذا الدرس التطبيقي حول الترميز. إذا أردت الاطّلاع على الحل النهائي، يمكنك الانتقال إلى https://github.com/android/identity-samples/tree/main/CredentialManager.

إذا كانت لديك أي أسئلة، يُرجى طرحها على StackOverflow باستخدام علامة passkey.

مزيد من المعلومات