Neueste Updates zur Credential Management API

Einige der hier beschriebenen Aktualisierungen werden in der Google I/O-Sitzung Sichere und nahtlose Anmeldung: Nutzerinteraktionen beibehalten erläutert:

Chrome 57

Mit Chrome 57 wurde diese wichtige Änderung an der Credential Management API vorgenommen.

Anmeldedaten können von einer anderen Subdomain aus freigegeben werden

Chrome kann jetzt mithilfe der Credential Management API Anmeldedaten abrufen, die in einer anderen Subdomain gespeichert sind. Wenn beispielsweise ein Passwort in login.example.com gespeichert ist, kann ein Skript für www.example.com es als eines der Kontoelemente im Dialogfeld zur Kontoauswahl anzeigen.

Du musst das Passwort explizit mit navigator.credentials.store() speichern. Wenn ein Nutzer durch Tippen auf das Dialogfeld Anmeldedaten auswählt, wird das Passwort übergeben und in den aktuellen Ursprung kopiert.

Nach dem Speichern ist das Passwort abwärts als Anmeldedaten ab demselben Ursprung (www.example.com) verfügbar.

Im folgenden Screenshot sind die unter login.aliexpress.com gespeicherten Anmeldedaten für m.aliexpress.com sichtbar und können vom Nutzer ausgewählt werden:

Kontoauswahl mit Anmeldedaten für die ausgewählte Subdomain

Chrome 60

In Chrome 60 wurden mehrere wichtige Änderungen an der Credential Management API vorgenommen:

Für die Featureerkennung sind Maßnahmen erforderlich

Wenn Sie wissen möchten, ob die Credential Management API für den Zugriff auf passwortbasierte und föderierte Anmeldedaten verfügbar ist, prüfen Sie, ob window.PasswordCredential oder window.FederatedCredential verfügbar ist.

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

PasswordCredential-Objekt enthält jetzt ein Passwort

Die Credential Management API verfolgte beim Umgang mit Passwörtern einen konservativen Ansatz. Passwörter wurden vor JavaScript verborgen, sodass Entwickler das PasswordCredential-Objekt zur Überprüfung über eine Erweiterung der fetch() API direkt an ihren Server senden müssen.

Dieser Ansatz brachte jedoch eine Reihe von Einschränkungen mit sich. Wir haben Feedback erhalten, dass Entwickler die API aus folgenden Gründen nicht verwenden konnten:

  • Sie mussten das Passwort als Teil eines JSON-Objekts senden.

  • Sie mussten den Hashwert des Passworts an ihren Server senden.

Nachdem wir eine Sicherheitsanalyse durchgeführt und erkannt hatten, dass das Verbergen von Passwörtern vor JavaScript nicht alle Angriffsvektoren so effektiv verhindert hat, wie wir gehofft hatten, haben wir uns dazu entschlossen, eine Änderung vorzunehmen.

Die Credential Management API enthält jetzt ein unformatiertes Passwort in ein zurückgegebenes Anmeldedatenobjekt, sodass Sie als Nur-Text darauf zugreifen können. Sie können die vorhandenen Methoden verwenden, um Anmeldedaten an Ihren Server zu senden:

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

Benutzerdefinierter Abruf wird bald eingestellt

Wenn Sie ermitteln möchten, ob Sie eine benutzerdefinierte fetch()-Funktion verwenden, prüfen Sie, ob sie ein PasswordCredential-Objekt oder ein FederatedCredential-Objekt als Wert des Attributs credentials verwendet. Beispiel:

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

Es wird empfohlen, eine reguläre fetch()-Funktion wie im vorherigen Codebeispiel zu verwenden oder eine XMLHttpRequest zu verwenden.

Bis Chrome 60 hat navigator.credentials.get() eine optionale unmediated-Eigenschaft mit einem booleschen Flag akzeptiert. Beispiel:

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

    // Sign-in
});

Mit der Einstellung unmediated: true wird verhindert, dass der Browser die Kontoauswahl anzeigt, wenn Anmeldedaten weitergegeben werden.

Das Flag wurde als Vermittlung erweitert. Die Vermittlung kann in folgenden Fällen erfolgen:

  • Ein Nutzer muss ein Konto auswählen, mit dem er sich anmelden möchte.

  • Ein Nutzer möchte sich nach dem navigator.credentials.requireUseMediation()-Aufruf explizit anmelden.

Wählen Sie für den Wert mediation eine der folgenden Optionen aus:

mediation Wert Im Vergleich zum booleschen Flag Behavior
silent Ist gleich unmediated: true Die Anmeldedaten wurden weitergegeben, ohne dass eine Kontoauswahl angezeigt wird.
optional Ist gleich unmediated: false Zeigt eine Kontoauswahl an, wenn preventSilentAccess() zuvor aufgerufen wurde.
required Eine neue Option Kontoauswahl immer anzeigen. Dies ist hilfreich, wenn Sie einem Nutzer ermöglichen möchten, ein Konto über das Dialogfeld zur Kontoauswahl zu wechseln.

In diesem Beispiel werden die Anmeldedaten übergeben, ohne dass eine Kontoauswahl angezeigt wird. Dies entspricht dem vorherigen Flag unmediated: true:

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

    // Sign-in
});

requireUserMediation() umbenannt in preventSilentAccess()

Die Methode navigator.credentials.requireUserMediation() wurde in navigator.credentials.preventSilentAccess() umbenannt, um sie gut an die neue Eigenschaft mediation anzupassen, die im get()-Aufruf angeboten wird.

Die umbenannte Methode verhindert, dass Anmeldedaten weitergegeben werden, ohne dass die Kontoauswahl angezeigt wird (manchmal ohne Nutzervermittlung aufgerufen). Das ist hilfreich, wenn sich ein Nutzer von einer Website abmeldet oder sich von einer Website abmeldet und beim nächsten Besuch nicht automatisch wieder angemeldet werden möchte.

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

Anmeldedatenobjekte asynchron mit der neuen Methode navigator.credentials.create() erstellen

Sie haben jetzt die Möglichkeit, Anmeldedatenobjekte asynchron mit der neuen Methode navigator.credentials.create() zu erstellen. Lesen Sie weiter, um einen Vergleich zwischen dem Synchronisierungs- und dem Asynchron-Ansatz zu vergleichen.

PasswordCredential-Objekt erstellen

Synchronisierungsansatz
let c = new PasswordCredential(form);
Asynchroner Ansatz (neu)
let c = await navigator.credentials.create({
    password: form
});

oder

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

FederatedCredential-Objekt erstellen

Synchronisierungsansatz
let c = new FederatedCredential({
    id:       'agektmr',
    name:     'Eiji Kitamura',
    provider: 'https://accounts.google.com',
    iconURL:  'https://*****'
});
Asynchroner Ansatz (neu)
let c = await navigator.credentials.create({
    federated: {
    id:       'agektmr',
    name:     'Eiji Kitamura',
    provider: 'https://accounts.google.com',
    iconURL:  'https://*****'
    }
});

Migrationsanleitung

Sie haben bereits eine Implementierung der Credential Management API? Wir bieten Ihnen einen Migrationsleitfaden, den Sie für das Upgrade auf die neue Version befolgen können.