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

تم شرح بعض التعديلات الموضّحة هنا في جلسة 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.

حتى الإصدار 60 من Chrome، كانت سمة 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);
أسلوب Async (جديد)
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؟ لدينا دليل نقل البيانات يمكنك اتّباعه للترقية إلى الإصدار الجديد.