آخر التعديلات على واجهة برمجة التطبيقات لإدارة بيانات الاعتماد

يمكنك الاطّلاع على بعض التعديلات الموضّحة هنا في جلسة مؤتمر Google I/O بعنوان تسجيل الدخول بأمان وسلس: الحفاظ على تفاعل المستخدمين:

Chrome 57

أدخل الإصدار 57 من Chrome هذا التغيير المهم في Credential Management API.

يمكن مشاركة بيانات الاعتماد من نطاق فرعي مختلف

يمكن الآن لمتصفّح Chrome استرداد بيانات اعتماد مخزّنة في نطاق فرعي مختلف باستخدام Credential Management API. مثلاً، في حال تخزين كلمة مرور في login.example.com، يمكن نص برمجي على www.example.com إظهارها كأحد عناصر الحساب في مربّع حوار أداة اختيار الحساب.

يجب تخزين كلمة المرور صراحةً باستخدام navigator.credentials.store()، بحيث عندما يختار المستخدم بيانات اعتماد من خلال النقر على مربّع الحوار، يتم تمرير كلمة المرور ونسخها إلى المصدر الحالي.

بعد تخزين كلمة المرور، تصبح متاحة كمستند اعتماد في المصدر نفسه بالضبط www.example.com فصاعدًا.

في لقطة الشاشة التالية، تكون معلومات بيانات الاعتماد المخزَّنة ضمن login.aliexpress.com مرئية لـ m.aliexpress.com ومتاحة للمستخدم للاختيار من بينها:

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

الإصدار 60 من Chrome

يقدّم الإصدار 60 من Chrome العديد من التغييرات المهمة على Credential Management API:

ميزة رصد العناصر تستدعي الانتباه

لمعرفة ما إذا كانت واجهة برمجة التطبيقات Credential Management API للوصول إلى بيانات الاعتماد المستندة إلى كلمة المرور متاحة، يُرجى التحقّق من توفّر window.PasswordCredential أو window.FederatedCredential.

if (window.PasswordCredential || window.FederatedCredential) {
  // The Credential Management API is available
}

عنصر واحد (PasswordCredential) يتضمّن الآن كلمة المرور

اعتمدت واجهة برمجة التطبيقات Credential Management API نهجًا متحفظًا في التعامل مع كلمات المرور. كان هذا الإجراء يخفي كلمات المرور من JavaScript، ما يتطلّب من المطوّرين إرسال عنصر PasswordCredential مباشرةً إلى خادمهم للتحقّق من صحتها من خلال إضافة إلى واجهة برمجة التطبيقات fetch().

ولكن هذا النهج فرض عددًا من القيود. تلقّينا ملاحظات تفيد بأنّه لا يمكن للمطوّرين استخدام واجهة برمجة التطبيقات للسببَين التاليَين:

  • كان عليهم إرسال كلمة المرور كجزء من عنصر JSON.

  • كان عليهم إرسال قيمة التجزئة لكلمة المرور إلى خادمهم.

بعد إجراء تحليل أمني وإدراك أنّ إخفاء كلمات المرور من JavaScript لم يمنع جميع جهات الهجوم بفعالية كما كنّا نأمل، قرّرنا إجراء تغيير.

تتضمّن واجهة برمجة التطبيقات Credential Management API الآن كلمة مرور أساسية في عنصر بيانات الاعتماد الذي يتم إرجاعه حتى تتمكّن من الوصول إليها كنص عادي. يمكنك استخدام الطرق الحالية لإرسال معلومات بيانات الاعتماد إلى خادمك:

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    mediation: 'silent'
}).then(passwordCred => {
    if (passwordCred) {
    let form = new FormData();
    form.append('email', passwordCred.id);
    form.append('password', passwordCred.password);
    form.append('csrf_token', csrf_token);
    return fetch('/signin', {
        method: 'POST',
        credentials: 'include',
        body: form
    });
    } else {

    // Fallback to sign-in form
    }
}).then(res => {
    if (res.status === 200) {
    return res.json();
    } else {
    throw 'Auth failed';
    }
}).then(profile => {
    console.log('Auth succeeded', profile);
});

سيتم قريبًا إيقاف ميزة "الاسترداد المخصّص" نهائيًا

لتحديد ما إذا كنت تستخدم دالة fetch() مخصّصة، تحقّق مما إذا كانت تستخدم عنصر PasswordCredential أو عنصر FederatedCredential كقيمة لسمة credentials، على سبيل المثال:

fetch('/signin', {
    method: 'POST',
    credentials: c
})

ننصحك باستخدام دالة fetch() عادية كما هو موضّح في مثال الرمز البرمجي السابق، أو استخدام دالة XMLHttpRequest.

حتى الإصدار Chrome 60، قبل navigator.credentials.get() السمة unmediated الاختيارية مع علامة منطقية. على سبيل المثال:

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    unmediated: true
}).then(c => {

    // Sign-in
});

يؤدي إعداد unmediated: true إلى منع المتصفّح من عرض محدِّد الحساب عند تمرير بيانات اعتماد.

تم توسيع العلامة الآن كتوسّط. يمكن أن يحدث التوسّط بين المستخدِمين في الحالات التالية:

  • يحتاج المستخدم إلى اختيار حساب لتسجيل الدخول باستخدامه.

  • يريد أحد المستخدمين تسجيل الدخول صراحةً بعد navigator.credentials.requireUseMediation() مكالمة.

حدِّد أحد الخيارات التالية للقيمة mediation:

قيمة mediation مقارنةً بالعلامة المنطقية السلوك
silent يساوي unmediated: true تم تمرير بيانات الاعتماد بدون إظهار محدد الحساب.
optional يساوي unmediated: false تعرِض أداة اختيار الحساب في حال سبق أن تم استدعاء preventSilentAccess().
required خيار جديد عرض محدد الحساب دائمًا. يكون هذا الخيار مفيدًا عندما تريد السماح للمستخدم بتبديل حساب باستخدام مربّع الحوار الأصلي لاختيار الحساب.

في هذا المثال، يتم تمرير بيانات الاعتماد بدون عرض أداة اختيار الحساب، أي ما يعادل العلامة السابقة unmediated: true:

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    mediation: 'silent'
}).then(c => {

    // Sign-in
});

تمت إعادة تسمية requireUserMediation() إلى preventSilentAccess().

وللتوافق بشكل جيد مع السمة mediation الجديدة المتوفرة في طلب get()، تمت إعادة تسمية الطريقة navigator.credentials.requireUserMediation() إلى navigator.credentials.preventSilentAccess().

تمنع الطريقة التي تمت إعادة تسميتها من تمرير بيانات اعتماد بدون عرض أداة اختيار الحساب (يُشار إليها أحيانًا باسم "بدون توسّط المستخدم"). يكون هذا مفيدًا عندما يسجّل المستخدم الخروج من موقع إلكتروني أو يلغى تسجيله منه ولا يريد إعادة تسجيل الدخول تلقائيًا في الزيارة التالية.

signoutUser();
if (navigator.credentials) {
    navigator.credentials.preventSilentAccess();
}

إنشاء عناصر بيانات الاعتماد بشكل غير متزامن باستخدام الطريقة الجديدة navigator.credentials.create()

يمكنك الآن إنشاء عناصر بيانات اعتماد بشكل غير متزامن باستخدام الطريقة الجديدة، navigator.credentials.create(). اطّلِع على المزيد من المعلومات للمقارنة بين أسلوبَي المزامنة وغير المتزامنة.

إنشاء عنصر PasswordCredential

نهج المزامنة
let c = new PasswordCredential(form);
نهج غير متزامن (جديد)
let c = await navigator.credentials.create({
    password: form
});

أو:

let c = await navigator.credentials.create({
    password: {
    id: id,
    password: password
    }
});

إنشاء عنصر FederatedCredential

نهج المزامنة
let c = new FederatedCredential({
    id:       'agektmr',
    name:     'Eiji Kitamura',
    provider: 'https://accounts.google.com',
    iconURL:  'https://*****'
});
أسلوب Async (جديد)
let c = await navigator.credentials.create({
    federated: {
    id:       'agektmr',
    name:     'Eiji Kitamura',
    provider: 'https://accounts.google.com',
    iconURL:  'https://*****'
    }
});

دليل نقل البيانات

هل لديك عملية تنفيذ حالية لواجهة برمجة التطبيقات Credential Management API؟ لدينا دليل نقل البيانات يمكنك اتّباعه للترقية إلى الإصدار الجديد.