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

1. قبل البدء

تشكِّل حلول المصادقة التقليدية عددًا من التحديات المتعلقة بالأمان وسهولة الاستخدام.

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

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

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

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

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

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

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

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

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

ما ستتعرَّف عليه

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

المتطلبات

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

  • جهاز Android يعمل بالإصدار 9 من نظام التشغيل Android أو إصدار أحدث (لمفاتيح المرور) والإصدار 4.4 من Android أو إصدار أحدث(لمصادقة كلمة المرور من خلال واجهة برمجة تطبيقات "إدارة بيانات الاعتماد")
  • يُفضَّل أن يكون الجهاز مزوّدًا بأداة استشعار حيوية.
  • احرص على تسجيل أحد المقاييس الحيوية (أو قفل الشاشة).
  • إصدار المكون الإضافي لـ Kotlin : 1.8.10

2. الإعداد

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

السماح بالاطّلاع على الحالة الأولية للتطبيق

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

  1. افتح التطبيق.
  2. ستظهر شاشة رئيسية تحتوي على زر "الاشتراك" و"تسجيل الدخول".
  3. يمكنك النقر على "اشتراك" للاشتراك باستخدام مفتاح مرور أو كلمة مرور.
  4. يمكنك النقر على "تسجيل الدخول" لتسجيل الدخول باستخدام مفتاح المرور كلمة مرور محفوظة.

8c0019ff9011950a.jpeg

للتعرّف على مفاتيح المرور وآلية عملها، يمكنك الاطّلاع على المقالة كيف تعمل مفاتيح المرور؟ .

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

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

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

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

داخل مدير بيانات الاعتماد -> app -> الرئيسي -> java -> SignUpFragment.kt، يمكنك رؤية حقل النص "username" وزرًا للاشتراك باستخدام مفتاح المرور

dcc5c529b310f2fb.jpeg

اجتياز التحدي واستجابة json الأخرى لاستدعاء createPasskey()

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

لحسن الحظ، لديك بالفعل استجابة وهمية في مواد العرض(RegFromServer.txt) تعرض مثل هذه المعلمات في هذا الدرس التطبيقي حول الترميز.

  • في تطبيقك، انتقِل إلى طريقة SignUpFragment.kt و"Find" وsignUpWithPasskeys التي ستكتب فيها منطق إنشاء مفتاح مرور والسماح للمستخدم بالدخول إليه. يمكنك العثور على الطريقة في نفس الفئة.
  • تحقق من القالب الآخر بتعليق لاستدعاء 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())

إنّ طريقة purchaseJsonFromServer() هذه هي طريقة تقرأ استجابة ملف json للتسجيل من مواد العرض وتعرض ملف json للتسجيل الذي سيتم تمريره أثناء إنشاء مفتاح المرور.

  • ابحث عن طريقة browseJsonFromServer() واستبدِل قائمة المهام بالتعليمة البرمجية التالية لعرض 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 للتسجيل من مواد العرض.
  • يتضمّن ملف json هذا 4 حقول سيتم استبدالها.
  • يجب أن يكون رقم تعريف المستخدم فريدًا حتى يتمكّن المستخدم من إنشاء مفاتيح مرور متعددة (إذا لزم الأمر). تستبدل <userId> مع إنشاء رقم تعريف المستخدم.
  • &lt;challenge&gt; يجب أيضًا أن يكون فريدًا؛ لذا ستنشئ تحديًا فريدًا عشوائيًا. سبق أن أضفت الطريقة إلى الرمز الخاص بك.

يتضمن مقتطف الرمز التالي نماذج الخيارات التي تتلقاها من الخادم:

{
  "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

يتوافق "كيان الطرف المعتمد" مع تفاصيل طلبك، ويحتاج إلى :

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

pubKeyCredParams

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

excludeCredentials

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

authenticatorSelection.authenticatorAttachment

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

residentKey

تشير إلى قيمة "مطلوبة" لإنشاء مفتاح مرور.

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

  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" أو أمر تصحيح أخطاء adb.

93022cb87c00f1fc.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" القيمة "صحيح" إلى أنّ الخادم (التجريبي) قد حفظ المفتاح العام لاستخدامه في المستقبل.
  • لقد ضبطت علامة SignedInThroughPasskeys على أنّها "صحيحة"، ما يشير إلى أنّك تسجّل الدخول باستخدام مفاتيح المرور.
  • بعد تسجيل الدخول، تتم إعادة توجيه المستخدم إلى الشاشة الرئيسية.

يتضمن مقتطف الرمز التالي أمثلة على الخيارات التي ينبغي لك الحصول عليها:

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

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

المعلّمات

الأوصاف

id

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

rawId

إصدار عنصر ArrayBuffer من رقم تعريف بيانات الاعتماد

response.clientDataJSON

عنصر ArrayBuffer تم ترميز بيانات العميل الخاصة به.

response.attestationObject

عنصر مصادقة مشفّر بتنسيق ArrayBuffer تحتوي على معلومات مهمة، مثل رقم تعريف الجهة المحظورة والعلامات والمفتاح العام.

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

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

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

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

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

SignUpFragment.kt

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

createPassword()
  • في طريقة createPassword()، تحتاج إلى إنشاء طلب كلمة مرور مثل هذا، واستبدل قائمة المهام بالرمز التالي :

SignUpFragment.kt

//TODO : CreatePasswordRequest with entered username and password

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

SignUpFragment.kt

//TODO : Create credential with created password request


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

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

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

629001f4a778d4fb.png

الحصول على التحدي والخيارات الأخرى لتمريره إلى استدعاء getPasskey()

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

لديك حاليًا استجابة وهمية في مواد العرض(AuthFromServer.txt) تعرض مثل هذه المَعلمات في هذا الدرس التطبيقي حول الترميز.

  • في تطبيقك، انتقِل إلى SignInFragment.kt، وابحث عن طريقة signInWithSavedCredentials التي ستكتب فيها منطق المصادقة باستخدام مفتاح المرور المحفوظ أو كلمة المرور المحفوظة، ثم تسمح للمستخدم بالدخول إلى :
  • تحقق من القالب الآخر بتعليق لاستدعاء 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)

إنّ طريقة BringAuthJsonFromServer() هذه هي طريقة تقرأ استجابة ملف json للمصادقة من الأصول وتُرجع ملف json للمصادقة لاسترداد جميع مفاتيح المرور المرتبطة بحساب المستخدم هذا.

المعلمة الثانية : clientDataHash - وهي تجزئة تُستخدم لإثبات هوية الجهة المعتمدة، ولا يتم ضبطها إلا في حال ضبط GetCredentialRequest.origin. بالنسبة إلى نموذج التطبيق، لا توجد قيمة فارغة.

تكون المعلمة الثالثة true إذا كنت تفضل عرض العملية فورًا عند عدم وجود بيانات اعتماد متاحة بدلاً من الرجوع إلى اكتشاف بيانات الاعتماد عن بُعد، وخطأ (تلقائي) في الحالات الأخرى.

  • ابحث عن طريقةFetchAuthJsonFromServer() واستبدال قائمة المهام بالرمز التالي لعرض 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 المستخدَمة عند إنشاء مفتاح المرور.

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

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(). يؤدي ذلك إلى إضافة قائمة بخيارات بيانات الاعتماد وسياق النشاط لعرض الخيارات في البطاقة السفلية في هذا السياق.
  • بعد نجاح الطلب، ستظهر لك بطاقة سفلية على الشاشة تسرد جميع بيانات الاعتماد التي تم إنشاؤها للحساب المرتبط.
  • ويمكن للمستخدمين الآن إثبات هويتهم من خلال المقاييس الحيوية أو قفل الشاشة وما إلى ذلك لمصادقة بيانات الاعتماد التي تم اختيارها.
  • لقد ضبطت علامة SignedInThroughPasskeys على أنّها "صحيحة"، ما يشير إلى أنّك تسجّل الدخول باستخدام مفاتيح المرور. وبخلاف ذلك، يتم عرض "خطأ".
  • ستتعامل مع إذن الوصول إلى طرق العرض المعروضة وتتعامل مع الاستثناءات في حال تعذُّر الطلب أو عدم نجاحه لسبب ما. هنا، يتم تسجيل رسائل الخطأ وعرضها على التطبيق في مربّع حوار الخطأ. يمكنك الاطّلاع على سجلّات الأخطاء الكاملة من خلال "استوديو Android" أو أمر تصحيح أخطاء adb.
  • وأخيرًا، تحتاج الآن إلى إكمال عملية التسجيل عن طريق إرسال بيانات اعتماد المفتاح العام إلى الخادم والسماح للمستخدم بالدخول. يتلقّى التطبيق عنصر بيانات اعتماد يحتوي على مفتاح عام يمكنك إرساله إلى الخادم للمصادقة عبر مفتاح المرور.

هنا، استخدمنا خادمًا وهميًا، لذا فإننا نعرض فقط 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() يعرض القيمة "صحيح" للإشارة إلى أنّ الخادم (mock) قد تحقّق من صحة المفتاح العام لاستخدامه في المستقبل.
  • بعد تسجيل الدخول، تتم إعادة توجيه المستخدم إلى الشاشة الرئيسية.

يتضمّن مقتطف الرمز التالي مثالاً على عنصر 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 لبيانات العميل يحتوي هذا الحقل على معلومات، مثل الاختبار والمصدر الذي يحتاج خادم الجهة المحظورة إلى التحقُّق منه.

response.authenticatorData

عنصر ArrayBuffer لبيانات برنامج المصادقة يتضمّن هذا الحقل معلومات مثل رقم تعريف الجهة المحظورة.

response.signature

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

response.userHandle

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

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

التجربة الآن

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

6- تهانينا!

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

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

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