Najnowsze aktualizacje interfejsu API do zarządzania danymi logowania

Niektóre opisane tu aktualizacje zostały omówione na konferencji Google I/O, Bezpieczne i łatwe logowanie: dbanie o zaangażowanie użytkowników:

Chrome 57

Ta ważna zmiana została wprowadzona w Chrome 57 Credential Management API.

Dane logowania mogą być udostępniane z innej subdomeny

Chrome może teraz pobrać dane logowania zapisane w innej subdomenie przy użyciu Credential Management API. Jeśli na przykład hasło jest przechowywane w usłudze login.example.com, skrypt w systemie www.example.com może go wyświetlić jako jeden z elementów konta w oknie wyboru konta.

Musisz bezpośrednio zapisać hasło za pomocą właściwości navigator.credentials.store(), dzięki czemu, gdy użytkownik wybierze dane logowania, klikając w oknie, hasło jest przekazywane i kopiowane do obecnego źródła.

Zapisze hasło będzie dostępne jako dane logowania w tym samym punkcie początkowym www.example.com i dalej.

Na zrzucie ekranu poniżej dane logowania są przechowywane w domenie login.aliexpress.com jest widoczna dla usługi m.aliexpress.com i użytkownik ma do wyboru następujące opcje:

Selektor konta wyświetlający dane logowania do wybranej subdomeny

Chrome 60

W Chrome 60 wprowadziliśmy kilka ważnych zmian Credential Management API:

Wykrywanie cech wymaga uwagi

Aby sprawdzić, czy interfejs Credential Management API do uzyskiwania dostępu do haseł sfederowane dane logowania są dostępne. Sprawdź, czy window.PasswordCredential lub Adres window.FederatedCredential jest dostępny.

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

PasswordCredential obiekt zawiera teraz hasło

Do obsługi haseł w interfejsie Credential Management API zastosowano zachowawcze podejście. Ukrył hasła przed JavaScriptem, co wymagało od programistów może wysłać obiekt PasswordCredential bezpośrednio na serwer do weryfikacji za pomocą rozszerzenia interfejsu API fetch().

Takie podejście skutkowało jednak szeregiem ograniczeń. Otrzymaliśmy informację, że deweloperzy nie mogą używać tego interfejsu API, ponieważ:

  • Musieć przesłać hasło w ramach obiektu JSON.

  • Musiał wysłać wartość skrótu hasła na swój serwer.

po przeprowadzeniu analizy zabezpieczeń i rozpoznaniu ukrycia haseł. nie powstrzymało wszystkich wektorów ataku tak skutecznie, jak się spodziewaliśmy, postanowiliśmy coś zmienić.

Interfejs Credential Management API zawiera teraz nieprzetworzone hasło w zwróconym obiekcie danych logowania, dzięki czemu masz do nich dostęp w postaci zwykłego tekstu. Możesz użyć istniejących metod, aby przesłać dane logowania na swój serwer:

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);
});

Niestandardowe pobieranie zostanie wkrótce wycofane

Aby sprawdzić, czy korzystasz z niestandardowej funkcji fetch(), Sprawdź, czy używa obiektu PasswordCredential czy FederatedCredential jako wartość właściwości credentials, na przykład:

fetch('/signin', {
    method: 'POST',
    credentials: c
})

Używając zwykłej funkcji fetch(), jak pokazano w poprzednim przykładzie kodu, lub zalecana jest właściwość XMLHttpRequest.

Do wersji Chrome 60 Użytkownik navigator.credentials.get() zaakceptował opcjonalną właściwość unmediated z flagą logiczną. Na przykład:

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    unmediated: true
}).then(c => {

    // Sign-in
});

Ustawienie unmediated: true uniemożliwia przeglądarce wyświetlanie selektora konta podczas przekazywania danych logowania.

Flaga jest teraz przedłużona jako zapośredniczenie. Zapośredniczenie użytkownika może mieć miejsce, gdy:

  • Użytkownik musi wybrać konto, na które będzie się logować.

  • Użytkownik chce się zalogować po navigator.credentials.requireUseMediation() rozmowie.

Wybierz jedną z tych opcji wartości mediation:

Wartość: mediation W porównaniu z flagą wartości logicznej Zachowanie
silent Równa się unmediated: true Dane logowania zostały przekazane bez wyświetlania selektora konta.
optional Równa się unmediated: false Wyświetla wybór konta, jeśli: preventSilentAccess() wywołano wcześniej.
required Nowa opcja Zawsze pokazuj opcję wyboru konta. Przydatne, gdy chcesz umożliwić użytkownikowi przełączanie konta w natywnym oknie wyboru konta.

W tym przykładzie dane logowania są przekazywane bez wyświetlania selektora konta, odpowiednik poprzedniej flagi, unmediated: true:

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    mediation: 'silent'
}).then(c => {

    // Sign-in
});

Zmieniono nazwę z requireUserMediation() na preventSilentAccess()

Aby dopasować je do nowej właściwości mediation oferowanej w wywołaniu get(), nazwa metody navigator.credentials.requireUserMediation() została zmieniona na navigator.credentials.preventSilentAccess()

Metoda ze zmienioną nazwą uniemożliwia przekazanie danych logowania bez wyświetlania selektora konta (czasami jest wywoływany bez zapośredniczenia użytkownika). Jest to przydatne, gdy użytkownik wyloguje się z witryny lub się wyrejestruje z jednego konta i nie chce logować się automatycznie przy następnej wizycie.

signoutUser();
if (navigator.credentials) {
    navigator.credentials.preventSilentAccess();
}

Asynchronicznie twórz obiekty danych logowania za pomocą nowej metody navigator.credentials.create()

Teraz możesz asynchronicznie tworzyć obiekty danych logowania za pomocą nowej metody: navigator.credentials.create(). W dalszej części artykułu znajdziesz porównanie metody synchronicznej i asynchronicznej.

Tworzenie obiektu PasswordCredential

Sposób synchronizacji
let c = new PasswordCredential(form);
Podejście asynchroniczne (nowe)
let c = await navigator.credentials.create({
    password: form
});

lub

let c = await navigator.credentials.create({
    password: {
    id: id,
    password: password
    }
});

Tworzenie obiektu FederatedCredential

Sposób synchronizacji
let c = new FederatedCredential({
    id:       'agektmr',
    name:     'Eiji Kitamura',
    provider: 'https://accounts.google.com',
    iconURL:  'https://*****'
});
Podejście asynchroniczne (nowe)
let c = await navigator.credentials.create({
    federated: {
    id:       'agektmr',
    name:     'Eiji Kitamura',
    provider: 'https://accounts.google.com',
    iconURL:  'https://*****'
    }
});

Przewodnik po migracji

Masz już wdrożenie interfejsu Credential Management API? Przygotowaliśmy dokument z przewodnikiem po migracji. .