Web Authentication API
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2021.
Sicherer Kontext: Diese Funktion ist nur in sicheren Kontexten (HTTPS) in einigen oder allen unterstützenden Browsern verfügbar.
Die Web Authentication API (WebAuthn) ist eine Erweiterung der Credential Management API, die starke Authentifizierung mit öffentlicher Schlüssel-Kryptographie ermöglicht und passwortlose Authentifizierung sowie sichere Multi-Faktor-Authentifizierung (MFA) ohne SMS-Nachrichten unterstützt.
Note: Passkeys sind ein bedeutender Anwendungsfall für die Web-Authentifizierung; sehen Sie sich Erstellen Sie einen Passkey für passwortlose Logins und Melden Sie sich mit einem Passkey durch automatisches Ausfüllen von Formularen an für Implementierungsdetails an. Siehe auch Google Identity > Passwortloses Login mit Passkeys.
WebAuthn-Konzepte und -Verwendung
WebAuthn nutzt asymmetrische (öffentlicher Schlüssel) Kryptographie anstelle von Passwörtern oder SMS-Nachrichten für die Registrierung, Authentifizierung und Multi-Faktor-Authentifizierung auf Websites. Dies hat einige Vorteile:
- Schutz vor Phishing: Ein Angreifer, der eine gefälschte Login-Website erstellt, kann sich nicht als der Benutzer anmelden, da die Signatur sich mit der Origin der Website ändert.
- Geringere Auswirkungen von Datenverletzungen: Entwickler müssen den öffentlichen Schlüssel nicht hashen, und wenn ein Angreifer Zugriff auf den öffentlichen Schlüssel erhält, der zur Verifizierung der Authentifizierung verwendet wird, kann er sich nicht authentifizieren, da er den privaten Schlüssel benötigt.
- Unempfindlich gegen Passwortangriffe: Einige Benutzer könnten Passwörter wiederverwenden, und ein Angreifer könnte das Passwort des Benutzers für eine andere Website erlangen (z. B. über eine Datenverletzung). Textpasswörter sind außerdem viel leichter zu bruteforcen als eine digitale Signatur.
Viele Websites verfügen bereits über Seiten, die es Benutzern ermöglichen, neue Konten zu registrieren oder sich bei einem bestehenden Konto anzumelden, und WebAuthn fungiert als Ersatz oder Erweiterung für den Authentifizierungsteil des Systems. Es erweitert die Credential Management API, abstrahiert die Kommunikation zwischen dem Benutzeragenten und einem Authentifikator und bietet folgende neue Funktionalitäten:
- Wenn
navigator.credentials.create()
mit derpublicKey
-Option verwendet wird, erstellt der Benutzeragent über einen Authentifikator neue Anmeldedaten — entweder zur Registrierung eines neuen Kontos oder zum Verknüpfen eines neuen asymmetrischen Schlüsselpaares mit einem bestehenden Konto.- Bei der Registrierung eines neuen Kontos werden diese Anmeldedaten auf einem Server (auch als Dienst oder als Vertrauenswürdiger Anbieter bezeichnet) gespeichert und können anschließend verwendet werden, um den Benutzer anzumelden.
- Das asymmetrische Schlüsselpaar wird im Authentifikator gespeichert, der dann zur Authentifizierung eines Benutzers bei einem Vertrauenswürdigen Anbieter, z. B. während der MFA, verwendet werden kann. Der Authentifikator kann in den Benutzeragenten integriert sein, in ein Betriebssystem wie Windows Hello, oder es kann sich um ein physisches Token wie einen USB- oder Bluetooth-Sicherheitsschlüssel handeln.
- Wenn
navigator.credentials.get()
mit derpublicKey
-Option verwendet wird, nutzt der Benutzeragent einen vorhandenen Satz von Anmeldedaten zur Authentifizierung bei einem Vertrauenswürdigen Anbieter (entweder als primäres Login oder um während der MFA einen zusätzlichen Faktor bereitzustellen, wie oben beschrieben).
In ihren grundlegendsten Formen empfangen sowohl create()
als auch get()
eine sehr große Zufallszahl, die "Herausforderung", vom Server und senden die von dem privaten Schlüssel signierte Herausforderung zurück an den Server. Dies beweist dem Server, dass ein Benutzer den für die Authentifizierung erforderlichen privaten Schlüssel besitzt, ohne Geheimnisse über das Netzwerk preiszugeben.
Hinweis: Die "Herausforderung" muss ein Puffer mit zufälligen Informationen von mindestens 16 Byte sein.
Erstellen eines Schlüsselpaares und Registrieren eines Benutzers
Um zu veranschaulichen, wie der Prozess zur Erstellung von Anmeldedaten funktioniert, beschreiben wir den typischen Ablauf, der abläuft, wenn ein Benutzer eine Anmeldeinformation bei einem Vertrauenswürdigen Anbieter registrieren möchte:
-
Der Vertrauenswürdige Anbieter-Server sendet Benutzer- und Informationen des Vertrauenswürdigen Anbieters zusammen mit der "Herausforderung" an die Web-App, die den Registrierungsprozess bearbeitet, unter Verwendung eines geeigneten sicheren Mechanismus (z. B. Fetch oder XMLHttpRequest).
Hinweis: Das Format zum Teilen von Informationen zwischen dem Vertrauenswürdigen Anbieter-Server und der Web-App liegt beim Entwickler der Anwendung. Ein empfohlener Ansatz ist der Austausch von JSON-Typ-Repräsentations-Objekten für Anmeldeinformationen und Anmeldeoptionen. Im
PublicKeyCredential
-Objekt wurden praktische Methoden zur Konvertierung von den JSON-Darstellungen in die von den Authentifizierungs-APIs benötigte Form erstellt:parseCreationOptionsFromJSON()
,parseRequestOptionsFromJSON()
undPublicKeyCredential.toJSON()
. -
Die Web-App initiiert die Erstellung eines neuen Anmeldeinformationssatzes über den Authentifikator im Auftrag des Vertrauenswürdigen Anbieters über einen Aufruf von
navigator.credentials.create()
. Dieser Aufruf erhält alspublicKey
-Option Gerätefähigkeiten, z. B. ob das Gerät seine eigene Benutzer-Authentifizierung bereitstellt (zum Beispiel durch biometrische Merkmale).Ein typischer
create()
-Aufruf könnte folgendermaßen aussehen:jslet credential = await navigator.credentials.create({ publicKey: { challenge: new Uint8Array([117, 61, 252, 231, 191, 241, ...]), rp: { id: "acme.com", name: "ACME Corporation" }, user: { id: new Uint8Array([79, 252, 83, 72, 214, 7, 89, 26]), name: "jamiedoe", displayName: "Jamie Doe" }, pubKeyCredParams: [ {type: "public-key", alg: -7} ] } });
Die Parameter des
create()
-Aufrufs werden an den Authentifikator übermittelt, zusammen mit einem SHA-256-Hash, der unterschrieben wird, um sicherzustellen, dass er nicht manipuliert wird. -
Nachdem der Authentifikator die Zustimmung des Benutzers eingeholt hat, generiert er ein Schlüsselpaar und gibt den öffentlichen Schlüssel sowie eine optional signierte Attestierung an die Web-App zurück. Diese wird bereitgestellt, wenn das von der
create()
-Methode zurückgegebenePromise
erfüllt wird, in Form einesPublicKeyCredential
-Objektinstanzes (diePublicKeyCredential.response
-Eigenschaft enthält die Attestierungsinformationen). -
Die Web-App leitet den
PublicKeyCredential
an den Server weiter, wiederum unter Verwendung eines geeigneten Mechanismus. -
Der Server speichert den öffentlichen Schlüssel in Verbindung mit der Benutzeridentität, um die Anmeldeinformationen für zukünftige Authentifizierungen zu behalten. Während dieses Prozesses führt er eine Reihe von Überprüfungen durch, um sicherzustellen, dass die Registrierung vollständig und nicht manipuliert war. Dazu gehören:
- Verifizierung, dass die Herausforderung dieselbe ist wie die gesendete Herausforderung.
- Sicherstellen, dass die Origin die erwartete Origin war.
- Validierung, dass die Signatur und die Attestierung die korrekte Zertifikatskette für das spezifische Modell des Authentifikators verwenden, das das Schlüsselpaar ursprünglich erzeugt hat.
Warnung: Attestierung bietet einem Vertrauenswürdigen Anbieter eine Möglichkeit, die Herkunft eines Authentifikators zu bestimmen. Vertrauenswürdige Anbieter sollten nicht versuchen, Positivlisten von Authentifikatoren zu führen.
Authentifizierung eines Benutzers
Nachdem ein Benutzer sich mit WebAuthn registriert hat, kann er sich beim Dienst authentifizieren (d. h. anmelden). Der Authentifizierungsprozess sieht dem Registrierungsprozess ähnlich, wobei die Hauptunterschiede darin bestehen, dass die Authentifizierung:
- Keine Benutzer- oder Informationen des Vertrauenswürdigen Anbieters erfordert.
- Eine Aussage mit dem zuvor für den Dienst generierten Schlüsselpaar erstellt, anstatt mit dem Schlüsselpaar des Authentifikators.
Ein typischer Authentifizierungsablauf sieht folgendermaßen aus:
-
Der Vertrauenswürdige Anbieter generiert eine "Herausforderung" und sendet sie zusammen mit einer Liste von Anmeldeinformationen des Vertrauenswürdigen Anbieters und Benutzers an den Benutzeragenten unter Verwendung eines geeigneten sicheren Mechanismus. Er kann auch angeben, wo die Anmeldeinformationen gesucht werden sollen, z. B. auf einem lokalen integrierten Authentifikator oder auf einem externen über USB, BLE usw.
-
Der Browser fordert den Authentifikator auf, die Herausforderung über einen Aufruf von
navigator.credentials.get()
zu signieren, welcher die Anmeldeinformationen in einerpublicKey
-Option enthält.Ein typischer
get()
-Aufruf könnte folgendermaßen aussehen:jslet credential = await navigator.credentials.get({ publicKey: { challenge: new Uint8Array([139, 66, 181, 87, 7, 203, ...]), rpId: "acme.com", allowCredentials: [{ type: "public-key", id: new Uint8Array([64, 66, 25, 78, 168, 226, 174, ...]) }], userVerification: "required", } });
Die Parameter des
get()
-Aufrufs werden an den Authentifikator übermittelt, um die Authentifizierung zu bearbeiten. -
Falls der Authentifikator eine der angegebenen Anmeldedaten enthält und in der Lage ist, die Herausforderung erfolgreich zu signieren, gibt er eine signierte Aussage an die Web-App zurück, nachdem er die Zustimmung des Benutzers erhalten hat. Diese wird bereitgestellt, wenn das von der
get()
-Methode zurückgegebenePromise
erfüllt wird, in Form einerPublicKeyCredential
-Objektinstanz (diePublicKeyCredential.response
-Eigenschaft enthält die Aussageninformationen). -
Die Web-App leitet die signierte Aussage an den Vertrauenswürdigen Anbieter-Server weiter, damit der Vertrauenswürdige Anbieter sie validieren kann. Die Validierungsüberprüfungen umfassen:
- Verwenden des öffentlichen Schlüssels, der während der Registrierungsanfrage gespeichert wurde, um die Signatur durch den Authentifikator zu validieren.
- Sicherstellen, dass die vom Authentifikator signierte Herausforderung mit der vom Server generierten Herausforderung übereinstimmt.
- Überprüfen, dass die ID des Vertrauenswürdigen Anbieters die erwartete für diesen Dienst ist.
-
Sobald vom Server überprüft, gilt der Authentifizierungsprozess als erfolgreich.
Zugriffskontrolle für die API
Die Verfügbarkeit von WebAuthn kann mit einer Berechtigungsrichtlinie gesteuert werden, die insbesondere zwei Direktiven spezifiziert:
publickey-credentials-create
: Kontrolliert die Verfügbarkeit vonnavigator.credentials.create()
mit derpublicKey
-Option.publickey-credentials-get
: Kontrolliert die Verfügbarkeit vonnavigator.credentials.get()
mit derpublicKey
-Option.
Beide Direktiven haben einen Standard-Positivlisten-Wert von "self"
, was bedeutet, dass diese Methoden standardmäßig in Top-Level-Dokumentkontexten verwendet werden können.
Darüber hinaus kann get()
in verschachtelten Browsing-Kontexten, die von derselben Herkunft wie das oberste Dokument geladen werden, verwendet werden.
get()
und create()
können in verschachtelten Browsing-Kontexten, die von verschiedenen Herkünften zum obersten Dokument geladen werden (z. B. in Cross-Origin-<iframes>
), verwendet werden, wenn dies von den Direktiven publickey-credentials-get
und publickey-credentials-create
erlaubt ist.
Für Cross-Origin-create()
-Aufrufe, bei denen die Berechtigung durch allow=
auf einem iframe gewährt wurde, muss der Frame auch Flüchtige Aktivierung haben.
Hinweis:
Wo eine Richtlinie die Nutzung dieser Methoden verbietet, wird das von ihnen zurückgegebene promises mit einem NotAllowedError
-DOMException
abgewiesen.
Grundlegende Zugriffskontrolle
Wenn Sie den Zugriff nur auf ein bestimmtes Subdomain erlauben möchten, könnten Sie es so bereitstellen:
Permissions-Policy: publickey-credentials-get=("https://subdomain.example.com")
Permissions-Policy: publickey-credentials-create=("https://subdomain.example.com")
Erlauben von eingebettetem create
- und get()
-Aufruf in einem <iframe>
Wenn Sie sich mit get()
oder create()
in einem <iframe>
authentifizieren möchten, gibt es einige Schritte zu befolgen:
-
Die Website, die die Seite des Vertrauenswürdigen Anbieters einbettet, muss die Berechtigung über ein
allow
-Attribut gewähren:-
Wenn
get()
verwendet wird:html<iframe src="https://auth.provider.com" allow="publickey-credentials-get *"> </iframe>
-
Wenn
create()
verwendet wird:html<iframe src="https://auth.provider.com" allow="publickey-credentials-create 'self' https://a.auth.provider.com https://b.auth.provider.com"> </iframe>
Das
<iframe>
muss auch Flüchtige Aktivierung haben, wenncreate()
Cross-Origin aufgerufen wird.
-
-
Die Website des Vertrauenswürdigen Anbieters muss die Berechtigung für den oben genannten Zugriff über einen
Permissions-Policy
-Header bereitstellen:httpPermissions-Policy: publickey-credentials-get=* Permissions-Policy: publickey-credentials-create=*
Oder um nur einer bestimmten URL zu erlauben, die Seite des Vertrauenswürdigen Anbieters in einem
<iframe>
einzubetten:httpPermissions-Policy: publickey-credentials-get=("https://subdomain.example.com") Permissions-Policy: publickey-credentials-create=("https://*.auth.provider.com")
Schnittstellen
AuthenticatorAssertionResponse
-
Bietet einem Dienst den Beweis, dass ein Authentifikator das notwendige Schlüsselpaar hat, um einen Authentifizierungsantrag erfolgreich zu bearbeiten, der durch einen Aufruf von
CredentialsContainer.get()
initiiert wurde. Verfügbar in derresponse
-Eigenschaft desPublicKeyCredential
-Instanzobjekts, das erhalten wird, wenn dasget()
Promise
erfüllt wird. AuthenticatorAttestationResponse
-
Das Ergebnis einer WebAuthn-Registrierung (d.h. eines Aufrufs von
CredentialsContainer.create()
). Es enthält Informationen über die Anmeldeinformation, die der Server benötigt, um WebAuthn-Erklärungen durchzuführen, wie ihre Anmelde-ID und den öffentlichen Schlüssel. Verfügbar in derresponse
-Eigenschaft desPublicKeyCredential
-Instanzobjekts, das erhalten wird, wenn dascreate()
Promise
erfüllt wird. AuthenticatorResponse
-
Die Basisschnittstelle für
AuthenticatorAttestationResponse
undAuthenticatorAssertionResponse
. PublicKeyCredential
-
Bietet Informationen über ein öffentliches / privates Schlüsselpaar, das eine Anmeldeinformation für das Einloggen in einen Dienst darstellt unter Verwendung eines un-phishable und datenbruchsicheren asymmetrischen Schlüsselpaares anstelle eines Passworts. Erhalten, wenn das von einem Aufruf von
create()
oderget()
zurückgegebenePromise
erfüllt wird.
Erweiterungen zu anderen Schnittstellen
CredentialsContainer.create()
, diepublicKey
-Option-
Ein Aufruf von
create()
mit einerpublicKey
-Option initiiert die Erstellung neuer asymmetrischer Schlüsselanmeldedaten über einen Authentifikator, wie oben erklärt. CredentialsContainer.get()
, diepublicKey
-Option-
Ein Aufruf von
get()
mit einerpublicKey
-Option veranlasst den Benutzeragenten, einen bestehenden Satz von Anmeldedaten zur Authentifizierung bei einem Vertrauenswürdigen Anbieter zu verwenden.
Beispiele
Demosites
- Mozilla Demo Website und dessen Quellcode.
- Google Demo Website und dessen Quellcode.
- WebAuthn.io Demo Website und dessen Quellcode.
- github.com/webauthn-open-source und dessen Client-Quellcode und Server-Quellcode
Anwendungsbeispiel
Hinweis:
Aus Sicherheitsgründen werden die Aufrufe der Web Authentication API (create()
und get()
) abgebrochen, wenn das Browserfenster den Fokus verliert, während der Aufruf in der Bearbeitung ist.
// sample arguments for registration
const createCredentialDefaultArgs = {
publicKey: {
// Relying Party (a.k.a. - Service):
rp: {
name: "Acme",
},
// User:
user: {
id: new Uint8Array(16),
name: "carina.p.anand@example.com",
displayName: "Carina P. Anand",
},
pubKeyCredParams: [
{
type: "public-key",
alg: -7,
},
],
attestation: "direct",
timeout: 60000,
challenge: new Uint8Array([
// must be a cryptographically random number sent from a server
0x8c, 0x0a, 0x26, 0xff, 0x22, 0x91, 0xc1, 0xe9, 0xb9, 0x4e, 0x2e, 0x17,
0x1a, 0x98, 0x6a, 0x73, 0x71, 0x9d, 0x43, 0x48, 0xd5, 0xa7, 0x6a, 0x15,
0x7e, 0x38, 0x94, 0x52, 0x77, 0x97, 0x0f, 0xef,
]).buffer,
},
};
// sample arguments for login
const getCredentialDefaultArgs = {
publicKey: {
timeout: 60000,
// allowCredentials: [newCredential] // see below
challenge: new Uint8Array([
// must be a cryptographically random number sent from a server
0x79, 0x50, 0x68, 0x71, 0xda, 0xee, 0xee, 0xb9, 0x94, 0xc3, 0xc2, 0x15,
0x67, 0x65, 0x26, 0x22, 0xe3, 0xf3, 0xab, 0x3b, 0x78, 0x2e, 0xd5, 0x6f,
0x81, 0x26, 0xe2, 0xa6, 0x01, 0x7d, 0x74, 0x50,
]).buffer,
},
};
// register / create a new credential
navigator.credentials
.create(createCredentialDefaultArgs)
.then((cred) => {
console.log("NEW CREDENTIAL", cred);
// normally the credential IDs available for an account would come from a server
// but we can just copy them from above…
const idList = [
{
id: cred.rawId,
transports: ["usb", "nfc", "ble"],
type: "public-key",
},
];
getCredentialDefaultArgs.publicKey.allowCredentials = idList;
return navigator.credentials.get(getCredentialDefaultArgs);
})
.then((assertion) => {
console.log("ASSERTION", assertion);
})
.catch((err) => {
console.log("ERROR", err);
});
Spezifikationen
Specification |
---|
Web Authentication: An API for accessing Public Key Credentials - Level 3 # iface-pkcredential |
Browser-Kompatibilität
BCD tables only load in the browser