Некоторые из описанных здесь обновлений рассматриваются в докладе Безопасный и удобный вход: как удержать пользователей на конференции Google I/O.
Chrome 57
В Chrome 57 появилось важное изменение в 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 и доступны для выбора пользователем.
Chrome 60
В Chrome 60 внесены важные изменения в Credential Management API:
Поскольку специальная функция
fetch()больше не требуется для получения пароля, скоро ее поддержка будет прекращена.navigator.credentials.get()теперь принимает перечислениеmediationвместо логического флагаunmediated.Файл
requireUserMediation()переименован вpreventSilentAccess().Новый метод
navigator.credentials.create()асинхронно создает объекты учетных данных.
Для распознавания объектов требуется действие
Чтобы узнать, доступен ли Credential Management API для доступа к учетным данным на основе паролей и федеративным учетным данным, проверьте, доступен ли window.PasswordCredential или window.FederatedCredential.
if (window.PasswordCredential || window.FederatedCredential) {
// The Credential Management API is available
}
Объект PasswordCredential теперь включает пароль
В Credential Management API использовался консервативный подход к обработке паролей.
Он скрывал пароли от JavaScript, требуя от разработчиков отправлять объект PasswordCredential непосредственно на свой сервер для проверки через расширение API fetch().
Однако у этого подхода есть ряд ограничений. Мы получили отзывы о том, что разработчики не могут использовать API по следующим причинам:
Они должны были отправить пароль как часть объекта JSON.
Они должны были отправить значение хеша пароля на свой сервер.
Проведя анализ безопасности, мы поняли, что скрытие паролей от JavaScript не предотвращает все векторы атак так эффективно, как мы надеялись, и решили внести изменения.
Теперь Credential Management API включает необработанный пароль в возвращаемый объект учетных данных, чтобы у вас был доступ к нему в виде обычного текста. Вы можете использовать существующие методы для передачи учетных данных на сервер:
navigator.credentials.get({
password: true,
federated: {
providers: [ 'https://accounts.google.com' ]
},
mediation: 'silent'
}).the>n(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() теперь принимает перечисление mediation
До версии 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&>#39;
}).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: 39;https://*****'
}
});
Руководство по переходу
Вы уже используете Credential Management API? Чтобы перейти на новую версию, воспользуйтесь руководством по переносу.