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

يتم شرح بعض التعديلات الموضّحة هنا في جلسة Google I/O، تسجيل الدخول الآمن والسلس: الحفاظ على تفاعل المستخدمين:

Chrome 57

قدّم Chrome 57 هذا التغيير المهم في Credential Management API.

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

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

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

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

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

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

Chrome 60

يقدّم الإصدار 60 من Chrome العديد من التغييرات المهمة على واجهة برمجة التطبيقات لإدارة بيانات الاعتماد:

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

لمعرفة ما إذا كانت واجهة برمجة التطبيقات لإدارة بيانات الاعتماد للوصول إلى بيانات الاعتماد المستندة إلى كلمة المرور وبيانات الاعتماد الموحّدة متاحة، تحقَّق من توفّر 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://*****'
});
النهج غير المتزامن (جديد)
let c = await navigator.credentials.create({
    federated: {
    id:       'agektmr',
    name:     'Eiji Kitamura',
    provider: 'https://accounts.google.com',
    iconURL:  'https://*****'
    }
});

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

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