Последние обновления Credential Management API

Некоторые из описанных здесь обновлений рассматриваются в докладе Безопасный и удобный вход: как удержать пользователей на конференции 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:

Для распознавания объектов требуется действие

Чтобы узнать, доступен ли 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.

До версии 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:  'https://*****'
    }
});

Руководство по переходу

Вы уже используете Credential Management API? Чтобы перейти на новую версию, воспользуйтесь руководством по переносу.