Некоторые из описанных здесь обновлений описаны в сеансе ввода-вывода Google «Безопасный и простой вход: поддержание активности пользователей» :
Хром 57
В Chrome 57 появилось это важное изменение в Credential Management 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
вместо логического флага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()
теперь принимает посредничество перечисления
До 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 управления учетными данными? У нас есть руководство по миграции, которому вы можете следовать, чтобы перейти на новую версию.