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

سنوضّح بعض التحديثات الموضَّحة هنا في جلسة مؤتمر 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 ومتاحة للمستخدم للاختيار من بينها:

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

إصدار 60 من Chrome

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

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

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

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

يحتوي العنصر "PasswordCredential" الآن على كلمة مرور.

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

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

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

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

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

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

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