Некоторые из описанных здесь обновлений объясняются в сессии Google I/O «Безопасный и простой вход: поддержание вовлеченности пользователей »:
Хром 57
В Chrome 57 появилось важное изменение в API управления учетными данными .
Учетные данные могут быть переданы из другого поддомена
Chrome теперь может извлекать учетные данные, хранящиеся в другом поддомене, используя API управления учетными данными . Например, если пароль хранится в login.example.com
, скрипт на www.example.com
может отображать его как один из элементов учетной записи в диалоговом окне выбора учетной записи.
Необходимо явно сохранить пароль с помощью navigator.credentials.store()
, чтобы при выборе пользователем учетных данных путем нажатия на диалоговое окно пароль передавался и копировался в текущий источник.
После сохранения пароль становится доступен в качестве учетных данных в том же самом источнике www.example.com
и далее.
На следующем снимке экрана учетные данные, хранящиеся на login.aliexpress.com
, видны m.aliexpress.com
и доступны пользователю для выбора:

Хром 60
Chrome 60 вносит несколько важных изменений в API управления учетными данными :
Поскольку пользовательская функция
fetch()
больше не требуется для получения пароля, она скоро будет объявлена устаревшей .navigator.credentials.get()
теперь принимаетmediation
enum вместо логического флагаunmediated
.requireUserMediation()
переименован вpreventSilentAccess()
.Новый метод
navigator.credentials.create()
асинхронно создает объекты учетных данных.
Обнаружение особенностей требует внимания
Чтобы узнать, доступен ли API управления учетными данными для доступа к учетным данным на основе пароля и федеративным учетным данным, проверьте, доступен ли window.PasswordCredential
или window.FederatedCredential
.
if (window.PasswordCredential || window.FederatedCredential) {
// The Credential Management API is available
}
Объект PasswordCredential
теперь включает пароль
API управления учетными данными использовал консервативный подход к обработке паролей. Он скрывал пароли от JavaScript, требуя от разработчиков отправлять объект PasswordCredential
непосредственно на свой сервер для проверки через расширение API fetch()
.
Но этот подход ввел ряд ограничений. Мы получили отзывы о том, что разработчики не могли использовать API, потому что:
Им пришлось отправить пароль как часть объекта JSON.
Им пришлось отправить хеш-значение пароля на свой сервер.
Проведя анализ безопасности и признав, что сокрытие паролей от JavaScript не предотвращает все векторы атак так эффективно, как мы надеялись, мы решили внести изменения.
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
.
navigator.credentials.get()
теперь принимает посредничество enum
До 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://*****'
}
});
Руководство по миграции
У вас есть существующая реализация API управления учетными данными? У нас есть руководство по миграции, которому вы можете следовать, чтобы перейти на новую версию.