Start · Sprachen · JavaScript · Referenz · PublicKeyCredentialCreationOptions

PublicKeyCredentialCreationOptions

Schnittstelle

Dictionary mit allen Angaben, die <code>navigator.credentials.create({ publicKey })</code> braucht, um per WebAuthn einen neuen Passkey bzw. ein Public-Key-Credential zu registrieren.

seit JavaScript WebAuthn Level 1 – Baseline: alle modernen Browser Kategorie: webapi

Signatur

interface PublicKeyCredentialCreationOptions

Beschreibung

PublicKeyCredentialCreationOptions ist kein Konstruktor, sondern ein einfaches Objekt (WebIDL-Dictionary). Du übergibst es als Wert der Eigenschaft publicKey an navigator.credentials.create(). Damit registrierst du über die Web Authentication API (WebAuthn) ein neues asymmetrisches Schlüsselpaar bei einem Authenticator, zum Beispiel einem Passkey im Betriebssystem, einem Sicherheitsschlüssel wie dem YubiKey oder Touch ID/Windows Hello.

Das Dictionary beschreibt die Relying Party (rp, also deine Website), den Benutzer (user), eine vom Server erzeugte Einmal-Challenge, die erlaubten Signaturalgorithmen (pubKeyCredParams) und optional Anforderungen an den Authenticator. Dazu gehören z. B. Plattform- oder externer Authenticator, auffindbare Credentials (Passkeys) und Benutzerverifikation per PIN oder Biometrie.

Normalerweise erzeugt der Server die Optionen, vor allem challenge und user.id. Der Client wandelt sie in ArrayBuffers um und reicht sie weiter. Die zurückgegebene PublicKeyCredential geht zur Prüfung an den Server zurück. Neuere Browser haben dafür PublicKeyCredential.parseCreationOptionsFromJSON(), das die Base64URL-Umwandlung übernimmt.

Parameter

Name Typ Default Beschreibung
$rp Pflicht { id?: string, name: string } Relying Party. name ist ein lesbarer Name. id ist die Domain, für die das Credential gilt (Standard: aktuelle Origin-Domain). Sie muss mit der aktuellen Domain übereinstimmen oder ein registrierbares Suffix davon sein.
$user Pflicht { id: BufferSource, name: string, displayName: string } Benutzerkonto. id ist ein undurchsichtiges Handle mit höchstens 64 Byte und ohne personenbezogene Daten. name ist z. B. eine E-Mail-Adresse, displayName der Anzeigename.
$challenge Pflicht BufferSource Kryptografisch zufälliger Wert vom Server (mind. 16 Byte). Er schützt vor Replay-Angriffen.
$pubKeyCredParams Pflicht Array<{ type: "public-key", alg: number }> Erlaubte Algorithmen als COSE-IDs, nach Vorliebe sortiert. Beispiele: -7 (ES256), -257 (RS256), -8 (EdDSA).
$timeout number browserabhängig Empfohlene maximale Wartezeit in Millisekunden. Der Browser behandelt den Wert nur als Hinweis.
$excludeCredentials Array<{ type: "public-key", id: BufferSource, transports?: string[] }> [] Bereits registrierte Credentials des Benutzers. Damit verhinderst du, dass derselbe Authenticator doppelt registriert wird.
$authenticatorSelection { authenticatorAttachment?: "platform"|"cross-platform", residentKey?: "discouraged"|"preferred"|"required", requireResidentKey?: boolean, userVerification?: "required"|"preferred"|"discouraged" } {} Anforderungen an den Authenticator. Für echte Passkeys setzt du residentKey: "required" und userVerification: "required" oder "preferred".
$attestation "none"|"indirect"|"direct"|"enterprise" "none" Legt fest, ob und wie der Authenticator ein Attestation Statement über seine Herkunft liefern soll.
$attestationFormats string[] [] Bevorzugte Attestation-Formate, z. B. "packed" oder "tpm" (WebAuthn Level 3).
$hints Array<"security-key"|"client-device"|"hybrid"> [] UI-Hinweise an den Browser, welche Art von Authenticator bevorzugt wird (WebAuthn Level 3, noch nicht überall unterstützt).
$extensions object Client-Erweiterungen, z. B. { credProps: true }, { prf: {} } oder { largeBlob: { support: "preferred" } }.

Rückgabewert

Typ
PublicKeyCredentialCreationOptions
Beschreibung
Das Dictionary selbst hat keinen Rückgabewert. Übergibst du es an navigator.credentials.create({ publicKey }), bekommst du ein Promise<PublicKeyCredential | null> mit einer AuthenticatorAttestationResponse.

Beispiele

Minimale Passkey-Registrierung

const registerPasskey = async () => {
  const publicKey = {
    challenge: crypto.getRandomValues(new Uint8Array(32)), // in der Praxis vom Server!
    rp: { name: 'Beispiel GmbH', id: location.hostname },
    user: {
      id: crypto.getRandomValues(new Uint8Array(16)),
      name: 'max@example.com',
      displayName: 'Max Mustermann'
    },
    pubKeyCredParams: [
      { type: 'public-key', alg: -7 },   // ES256
      { type: 'public-key', alg: -257 }  // RS256
    ],
    authenticatorSelection: {
      residentKey: 'required',
      userVerification: 'preferred'
    },
    timeout: 60000,
    attestation: 'none'
  };

  const credential = await navigator.credentials.create({ publicKey });
  console.log(credential.type, credential.id);
};

document.querySelector('#register').addEventListener('click', registerPasskey);
public-key AbC123...xyz

Optionen vom Server laden und Base64URL umwandeln

const b64urlToBuffer = (s) => {
  const b64 = s.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(s.length / 4) * 4, '=');
  return Uint8Array.from(atob(b64), (c) => c.charCodeAt(0)).buffer;
};

const register = async () => {
  const res = await fetch('/webauthn/register/options', { method: 'POST' });
  const json = await res.json();

  // Moderner Weg, falls verfügbar
  const publicKey = PublicKeyCredential.parseCreationOptionsFromJSON
    ? PublicKeyCredential.parseCreationOptionsFromJSON(json)
    : {
        ...json,
        challenge: b64urlToBuffer(json.challenge),
        user: { ...json.user, id: b64urlToBuffer(json.user.id) },
        excludeCredentials: (json.excludeCredentials ?? []).map((c) => ({
          ...c,
          id: b64urlToBuffer(c.id)
        }))
      };

  const credential = await navigator.credentials.create({ publicKey });

  await fetch('/webauthn/register/verify', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(credential.toJSON()) // toJSON(): neuere Browser
  });
};

Doppelte Registrierung verhindern und Fehler behandeln

const createWithExclusion = async (options, existingIds) => {
  const publicKey = {
    ...options,
    excludeCredentials: existingIds.map((id) => ({ type: 'public-key', id })),
    extensions: { credProps: true }
  };

  try {
    const cred = await navigator.credentials.create({ publicKey });
    const { credProps } = cred.getClientExtensionResults();
    console.log('Auffindbar (Passkey):', credProps?.rk);
    return cred;
  } catch (err) {
    if (err.name === 'InvalidStateError') {
      console.warn('Dieser Authenticator ist bereits registriert.');
    } else if (err.name === 'NotAllowedError') {
      console.warn('Abgebrochen oder Zeitüberschreitung.');
    } else {
      throw err;
    }
  }
};
Auffindbar (Passkey): true