Neueste Updates zur Credential Management API

Einige der hier beschriebenen Änderungen werden in der Google I/O-Sitzung Secure and Seamless Sign-In: Keeping Users Engaged (Sichere und nahtlose Anmeldung: Nutzer binden) erläutert:

Chrome 57

In Chrome 57 wurde diese wichtige Änderung an der Credential Management API eingeführt.

Anmeldedaten können über eine andere Subdomain 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 es in einem Script auf login.example.com im Dialogfeld für die Kontoauswahl als eines der Kontoelemente angezeigt werden.www.example.com

Sie müssen das Passwort explizit mit navigator.credentials.store() speichern, damit das Passwort übergeben und in den aktuellen Ursprung kopiert wird, wenn ein Nutzer durch Tippen auf das Dialogfeld Anmeldedaten auswählt.

Nach dem Speichern ist das Passwort ab www.example.com als Anmeldedaten an genau derselben Quelle verfügbar.

Im folgenden Screenshot sind die Anmeldedaten, die unter login.aliexpress.com gespeichert sind, 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

Mit Chrome 60 werden mehrere wichtige Änderungen an der Credential Management API eingeführt:

Funktionserkennung erfordert Aufmerksamkeit

Ob die Credential Management API für den Zugriff auf passwortbasierte und föderierte Anmeldedaten verfügbar ist, erkennen Sie daran, ob window.PasswordCredential oder window.FederatedCredential verfügbar ist.

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

Das PasswordCredential-Objekt enthält jetzt das Passwort

Bei der Credential Management API wurde ein konservativer Ansatz für die Passwortverwaltung gewählt. Sie verborgen Passwörter vor JavaScript, sodass Entwickler das PasswordCredential-Objekt zur Validierung über eine Erweiterung der fetch() API direkt an ihren Server senden mussten.

Dieser Ansatz führte jedoch zu einer Reihe von Einschränkungen. Wir haben Feedback erhalten, dass Entwickler die API nicht verwenden konnten, weil:

  • Das Passwort musste als Teil eines JSON-Objekts gesendet werden.

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

Nach einer Sicherheitsanalyse haben wir festgestellt, dass das Verstecken von Passwörtern vor JavaScript nicht alle Angriffsvektoren so effektiv verhindert, wie wir gehofft hatten. Deshalb haben wir uns entschlossen, eine Änderung vorzunehmen.

Die Credential Management API enthält jetzt ein Rohpasswort in einem zurückgegebenen Anmeldedatenobjekt, sodass Sie darauf als Klartext zugreifen können. Sie können vorhandene 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);
});

Benutzerdefinierte Abrufe werden bald eingestellt

Ob Sie eine benutzerdefinierte fetch()-Funktion verwenden, erkennen Sie daran, ob ein PasswordCredential-Objekt oder ein FederatedCredential-Objekt als Wert der credentials-Property verwendet wird, z. B.:

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

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

Bis Chrome 60 wurde für 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
});

Wenn Sie unmediated: true festlegen, wird die Kontoauswahl nicht angezeigt, wenn Anmeldedaten übergeben werden.

Das Flag wird jetzt als Vermittlung erweitert. Die Nutzervermittlung 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()-Anruf explizit anmelden.

Wählen Sie einen der folgenden Werte für mediation aus:

mediation Wert Im Vergleich zu einem booleschen Flag Verhalten
silent Ist gleich unmediated: true Anmeldedaten wurden übergeben, ohne dass eine Kontoauswahl angezeigt wurde.
optional Ist gleich unmediated: false Zeigt eine Kontoauswahl an, wenn preventSilentAccess() zuvor aufgerufen wurde.
required Eine neue Option Eine Kontoauswahl immer anzeigen. Nützlich, wenn Sie Nutzern erlauben möchten, über das native Dialogfeld für die Kontoauswahl das Konto zu wechseln.

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

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

    // Sign-in
});

requireUserMediation() in preventSilentAccess() umbenannt

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

Mit der umbenannten Methode wird verhindert, dass Anmeldedaten übergeben werden, ohne dass die Kontoauswahl angezeigt wird (manchmal auch als „ohne Nutzervermittlung“ bezeichnet). Das ist nützlich, wenn sich ein Nutzer von einer Website abmeldet oder sich dort abmeldet und nicht beim nächsten Besuch automatisch wieder angemeldet werden möchte.

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

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

Mit der neuen Methode navigator.credentials.create() können Sie jetzt asynchron Anmeldedatenobjekte erstellen. Im Folgenden finden Sie einen Vergleich zwischen dem synchronen und dem asynchronen Ansatz.

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

Haben Sie bereits eine Implementierung der Credential Management API? In unserem Migrationsleitfaden finden Sie eine Anleitung zum Upgrade auf die neue Version.