Signatur
Beschreibung
Die schreibgeschützte Eigenschaft id liefert den Bezeichner eines PublicKeyCredential, also eines WebAuthn-Schlüsselpaars bzw. Passkeys. Sie wird von Credential geerbt. Der Wert ist die Credential-ID in Base64URL-Kodierung (ohne Padding). Der Authenticator erzeugt sie bei der Registrierung.
Inhaltlich entspricht id der Eigenschaft rawId. rawId liefert dieselben Bytes allerdings als ArrayBuffer. In der Praxis schickt man id nach navigator.credentials.create() an den Server und speichert sie dort zusammen mit dem öffentlichen Schlüssel beim Benutzerkonto. Beim Login mit navigator.credentials.get() zeigt id an, welches registrierte Credential der Benutzer gewählt hat. Damit findet der Server den passenden öffentlichen Schlüssel für die Signaturprüfung.
Außerdem braucht man die ID, um bei späteren Aufrufen die Liste allowCredentials (Anmeldung) oder excludeCredentials (keine doppelte Registrierung) zu füllen. Dort wird sie allerdings als BufferSource erwartet, also als Bytes und nicht als String.
Rückgabewert
A–Z, a–z, 0–9, -, _, ohne =-Padding).Beispiele
Credential-ID nach der Registrierung an den Server senden
const registerPasskey = async (options) => {
// options kommen vom Server (challenge, rp, user, pubKeyCredParams ...)
const credential = await navigator.credentials.create({ publicKey: options });
console.log(credential.type); // "public-key"
console.log(credential.id); // Base64URL-String
await fetch('/webauthn/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
// toJSON() serialisiert alle Felder, id bleibt ein String
body: JSON.stringify(credential.toJSON())
});
};
Beim Login das gewählte Credential erkennen
const login = async (challenge) => {
const assertion = await navigator.credentials.get({
publicKey: { challenge, userVerification: 'preferred' }
});
// Der Server sucht mit der ID den gespeicherten öffentlichen Schlüssel
const res = await fetch('/webauthn/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ credentialId: assertion.id, response: assertion.toJSON().response })
});
return res.ok;
};
id und rawId vergleichen bzw. ineinander umwandeln
// Base64URL-String -> Uint8Array (z. B. für allowCredentials)
const base64urlToBytes = (str) => {
const b64 = str.replace(/-/g, '+').replace(/_/g, '/');
const padded = b64 + '='.repeat((4 - (b64.length % 4)) % 4);
return Uint8Array.from(atob(padded), (c) => c.charCodeAt(0));
};
const checkId = (credential) => {
const fromId = base64urlToBytes(credential.id);
const fromRaw = new Uint8Array(credential.rawId);
const same = fromId.length === fromRaw.length && fromId.every((b, i) => b === fromRaw[i]);
console.log('id und rawId identisch:', same);
};
// Späterer Login nur mit bekannten Credentials:
const buildAllowList = (storedIds) =>
storedIds.map((id) => ({ type: 'public-key', id: base64urlToBytes(id) }));
// Wichtig · Fallstricke
- Base64URL, nicht Base64: Mit
atob()lässt sichidnicht direkt dekodieren. Vorher müssen-/_ersetzt und das Padding ergänzt werden. Neuere Browser bieten dafürPublicKeyCredential.parseCreationOptionsFromJSON()bzw.parseRequestOptionsFromJSON()undUint8Array.fromBase64(). - In
allowCredentials/excludeCredentialsmuss die ID alsBufferSourceübergeben werden. Ein String an dieser Stelle führt zu einemTypeError. - Die ID ist kein Geheimnis und kein Authentifizierungsbeweis. Der Server muss immer die Signatur, die Challenge und die Origin prüfen. Die ID nicht als Session-Token missbrauchen.
- Bei auffindbaren Credentials (Passkeys) kann die ID bis zu 1023 Byte lang sein. Das Datenbankfeld muss entsprechend groß angelegt werden.
- WebAuthn funktioniert nur in sicheren Kontexten (HTTPS oder
localhost). Unterstützt wird es in allen aktuellen Browsern (Chrome, Edge, Firefox, Safari).