Zu User-Agent-Client-Hints migrieren

Strategien zur Migration Ihrer Website vom User-Agent-String zu den neuen User-Agent-Client-Hints.

Der User-Agent-String ist eine erhebliche passive Fingerprinting-Oberfläche in Browsern, die schwierig zu verarbeiten ist. Es gibt jedoch viele gute Gründe, User-Agent-Daten zu erheben und zu verarbeiten. Daher ist eine bessere Lösung erforderlich. Mit User-Agent-Client-Hinweisen können Sie sowohl explizit angeben, dass Sie User-Agent-Daten benötigen, als auch Methoden angeben, mit denen die Daten in einem nutzerfreundlichen Format zurückgegeben werden.

In diesem Artikel erfahren Sie, wie Sie Ihren Zugriff auf User-Agent-Daten prüfen und die Verwendung von User-Agent-Strings zu User-Agent-Client-Hints migrieren.

Erhebung und Nutzung von User-Agent-Daten prüfen

Wie bei jeder Form der Datenerhebung sollten Sie immer wissen, warum Sie die Daten erheben. Unabhängig davon, ob Sie Maßnahmen ergreifen oder nicht, sollten Sie zuerst herausfinden, wo und warum Sie User-Agent-Daten verwenden.

Wenn Sie nicht wissen, ob und wo User-Agent-Daten verwendet werden, können Sie in Ihrem Front-End-Code nach navigator.userAgent und in Ihrem Back-End-Code nach dem User-Agent-HTTP-Header suchen. Außerdem sollten Sie Ihren Front-End-Code auf die Verwendung bereits eingestellter Funktionen wie navigator.platform und navigator.appVersion prüfen.

Überlegen Sie aus funktionaler Sicht, wo in Ihrem Code Sie Folgendes erfassen oder verarbeiten:

  • Name oder Version des Browsers
  • Name oder Version des Betriebssystems
  • Marke oder Modell des Geräts
  • CPU-Typ, -Architektur oder -Bitanzahl (z. B. 64-Bit)

Möglicherweise verwenden Sie auch eine Bibliothek oder einen Dienst eines Drittanbieters, um den User-Agent zu verarbeiten. Prüfen Sie in diesem Fall, ob die Website aktualisiert wird, um User-Agent-Client-Hints zu unterstützen.

Verwenden Sie nur grundlegende User-Agent-Daten?

Standardmäßig sind folgende User-Agent-Client-Hints verfügbar:

  • Sec-CH-UA: Browsername und Haupt-/wichtige Version
  • Sec-CH-UA-Mobile: Boolescher Wert, der ein Mobilgerät angibt
  • Sec-CH-UA-Platform: Name des Betriebssystems
    • Hinweis: Diese Änderung wurde in der Spezifikation berücksichtigt und wird demnächst in Chrome und anderen Chromium-basierten Browsern übernommen.

Die vorgeschlagene reduzierte Version des User-Agent-Strings enthält diese grundlegenden Informationen auch weiterhin auf abwärtskompatible Weise. Anstelle von Chrome/90.0.4430.85 würde der String beispielsweise Chrome/90.0.0.0 enthalten.

Wenn Sie den User-Agent-String nur auf den Browsernamen, die Hauptversion oder das Betriebssystem prüfen, funktioniert Ihr Code weiterhin, Sie sehen jedoch wahrscheinlich Warnungen zur Einstellung.

Sie können und sollten zu User-Agent-Client-Hints migrieren. Möglicherweise verhindern aber Altcode oder Ressourceneinschränkungen dies. Durch die rückwärtskompatible Reduzierung der Informationen im User-Agent-String soll sichergestellt werden, dass der vorhandene Code zwar weniger detaillierte Informationen erhält, aber die grundlegenden Funktionen beibehalten werden.

Strategie: On-Demand-clientseitige JavaScript API

Wenn Sie derzeit navigator.userAgent verwenden, sollten Sie navigator.userAgentData bevorzugen, bevor Sie auf das Parsen des User-Agent-Strings zurückgreifen.

if (navigator.userAgentData) {
  // use new hints
} else {
  // fall back to user-agent string parsing
}

Wenn Sie prüfen möchten, ob es sich um ein Mobilgerät oder einen Computer handelt, verwenden Sie den booleschen Wert mobile:

const isMobile = navigator.userAgentData.mobile;

userAgentData.brands ist ein Array von Objekten mit den Properties brand und version, in denen der Browser seine Kompatibilität mit diesen Marken auflisten kann. Sie können direkt als Array darauf zugreifen oder mit einem some()-Aufruf prüfen, ob ein bestimmter Eintrag vorhanden ist:

function isCompatible(item) {
  // In real life you most likely have more complex rules here
  return ['Chromium', 'Google Chrome', 'NewBrowser'].includes(item.brand);
}
if (navigator.userAgentData.brands.some(isCompatible)) {
  // browser reports as compatible
}

Wenn Sie einen der detaillierteren User-Agent-Werte mit hoher Entropie benötigen, müssen Sie ihn angeben und das Ergebnis in der zurückgegebenen Promise prüfen:

navigator.userAgentData.getHighEntropyValues(['model'])
  .then(ua => {
    // requested hints available as attributes
    const model = ua.model
  });

Diese Strategie kann auch verwendet werden, wenn Sie von der serverseitigen Verarbeitung zur clientseitigen Verarbeitung wechseln möchten. Für die JavaScript API ist kein Zugriff auf HTTP-Anfrageheader erforderlich. User-Agent-Werte können also jederzeit angefordert werden.

Strategie: Statischer serverseitiger Header

Wenn Sie den Anfrageheader User-Agent auf dem Server verwenden und Ihre Anforderungen an diese Daten auf der gesamten Website relativ konsistent sind, können Sie die gewünschten Clienthinweise als statischen Satz in Ihren Antworten angeben. Dies ist ein relativ einfacher Ansatz, da Sie ihn in der Regel nur an einem Ort konfigurieren müssen. Sie können sich beispielsweise in Ihrer Webserverkonfiguration befinden, wenn Sie dort bereits Header, in Ihrer Hosting-Konfiguration oder in der Top-Level-Konfiguration des Frameworks oder der Plattform, die Sie für Ihre Website verwenden, hinzugefügt haben.

Diese Strategie eignet sich, wenn Sie die gesendeten Antworten basierend auf den User-Agent-Daten transformieren oder anpassen.

Da Browser oder andere Clients unterschiedliche Standardhinweise bereitstellen, empfiehlt es sich, alles Notwendige anzugeben, selbst wenn dies normalerweise standardmäßig der Fall ist.

Die aktuellen Standardeinstellungen für Chrome würden beispielsweise so dargestellt:

⬇️ Antwort-Header

Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA

Wenn Sie das Gerätemodell auch in Antworten erhalten möchten, senden Sie Folgendes:

⬇️ Antwort-Header

Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA

Bei der serverseitigen Verarbeitung sollten Sie zuerst prüfen, ob der gewünschte Sec-CH-UA-Header gesendet wurde, und dann auf den User-Agent-Header zurückgreifen, falls er nicht verfügbar ist.

Strategie: Hinweise an ursprungsübergreifende Anfragen delegieren

Wenn Sie unterbrechungsfreie oder websiteübergreifende Unterressourcen anfordern, für die User-Agent-Client-Hints in ihren Anfragen gesendet werden müssen, müssen Sie die gewünschten Hinweise explizit mit einer Berechtigungsrichtlinie angeben.

Angenommen, https://blog.site hostet Ressourcen auf https://cdn.site, die Ressourcen zurückgeben können, die für ein bestimmtes Gerät optimiert sind. https://blog.site kann den Sec-CH-UA-Model-Hinweis anfordern, muss ihn aber explizit mit dem Permissions-Policy-Header an https://cdn.site delegieren. Die Liste der richtliniengesteuerten Hinweise ist im Infrastrukturentwurf für Clients verfügbar.

⬇️ Antwort von blog.site, in der der Hinweis weitergeleitet wird

Accept-CH: Sec-CH-UA-Model
Permissions-Policy: ch-ua-model=(self "https://cdn.site")

⬆️ Anfragen an Unterressourcen auf cdn.site müssen den delegierten Hinweis enthalten

Sec-CH-UA-Model: "Pixel 5"

Sie können mehrere Hinweise für mehrere Ursprünge angeben, nicht nur aus dem Bereich ch-ua:

⬇️ Antwort von blog.site, in der mehrere Hinweise an mehrere Ursprünge delegiert werden

Accept-CH: Sec-CH-UA-Model, DPR
Permissions-Policy: ch-ua-model=(self "https://cdn.site"),
                    ch-dpr=(self "https://cdn.site" "https://img.site")

Strategie: Hinweise an iFrames delegieren

Mehrfach-Quell-iFrames funktionieren ähnlich wie mehrmals quellgebundene Ressourcen. Die Hinweise, die Sie delegieren möchten, geben Sie jedoch im Attribut allow an.

⬇️ Antwort von blog.site

Accept-CH: Sec-CH-UA-Model

↪️ HTML für blog.site

<iframe src="https://widget.site" allow="ch-ua-model"></iframe>

⬆️ Anfrage an widget.site

Sec-CH-UA-Model: "Pixel 5"

Das allow-Attribut im iFrame überschreibt alle Accept-CH-Header, die widget.site selbst senden kann. Achten Sie daher darauf, dass Sie alles angegeben haben, was für die Website des iFrames erforderlich ist.

Strategie: Dynamische serverseitige Hinweise

Wenn Sie für bestimmte Teile des Kaufprozesses eine größere Auswahl an Hinweisen benötigen als für den Rest der Website, können Sie diese Hinweise auf Anfrage anfordern, anstatt sie statisch auf der gesamten Website anzuzeigen. Dies ist zwar komplizierter, aber wenn Sie bereits unterschiedliche Header für jede Route festlegen, ist dies möglicherweise möglich.

Wichtig ist, dass jede Instanz des Accept-CH-Headers den vorhandenen Satz effektiv überschreibt. Wenn Sie den Header also dynamisch festlegen, muss jede Seite den vollständigen Satz der erforderlichen Hinweise anfordern.

Angenommen, Sie haben einen Bereich auf Ihrer Website, in dem Sie Symbole und Steuerelemente bereitstellen möchten, die dem Betriebssystem des Nutzers entsprechen. Dazu können Sie zusätzlich Sec-CH-UA-Platform-Version einbinden, um die entsprechenden Unterressourcen bereitzustellen.

⬇️ Antwortheader für /blog

Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA

⬇️ Antwortheader für /app

Accept-CH: Sec-CH-UA-Mobile, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA

Strategie: Serverseitige Hinweise bei der ersten Anfrage erforderlich

Es kann vorkommen, dass Sie bei der allerersten Anfrage mehr als die Standard-Hinweise benötigen. Dies ist jedoch eher selten der Fall. Sehen Sie sich daher die Begründung an.

Die erste Anfrage ist die allererste Anfrage auf oberster Ebene für diesen Ursprung, die in dieser Browser-Sitzung gesendet wird. Die Standardhinweise umfassen den Browsernamen mit Hauptversion, die Plattform und die Anzeige für Mobilgeräte. Die Frage ist also, ob Sie erweiterte Daten beim ersten Seitenaufbau benötigen.

Für weitere Hinweise zur ersten Anfrage haben Sie zwei Möglichkeiten. Als Erstes können Sie den Header Critical-CH verwenden. Dieser hat dasselbe Format wie Accept-CH, teilt dem Browser aber mit, dass er die Anfrage sofort wiederholen soll, wenn die erste ohne den wichtigen Hinweis gesendet wurde.

⬆️ Erste Anfrage

[With default headers]

⬇️ Antwort-Header

Accept-CH: Sec-CH-UA-Model
Critical-CH: Sec-CH-UA-Model

🔃 Der Browser versucht, die ursprüngliche Anfrage mit dem zusätzlichen Header noch einmal zu senden.

[With default headers + …]
Sec-CH-UA-Model: Pixel 5

Dies führt zu einem Overhead bei der Wiederholung der allerersten Anfrage, die Implementierungskosten sind jedoch relativ gering. Senden Sie den zusätzlichen Header und der Browser erledigt den Rest.

Wenn Sie wirklich beim ersten Laden der Seite zusätzliche Hinweise benötigen, erstellt das Client Hints Reliability-Angebot eine Route, um Hinweise in den Einstellungen auf Verbindungsebene anzugeben. Dazu wird die Application-Layer Protocol Settings(ALPS)-Erweiterung von TLS 1.3 verwendet, um diese frühzeitige Weitergabe von Hinweisen bei HTTP/2- und HTTP/3-Verbindungen zu ermöglichen. Das Projekt befindet sich noch in einem sehr frühen Stadium. Wenn Sie Ihre eigenen TLS- und Verbindungseinstellungen aktiv verwalten, ist jetzt der ideale Zeitpunkt, um sich zu beteiligen.

Strategie: Legacy-Support

Möglicherweise haben Sie auf Ihrer Website älteren Code oder Drittanbietercode, der von navigator.userAgent abhängt, einschließlich Teilen des User-Agent-Strings, die gekürzt werden. Langfristig sollten Sie zu den entsprechenden navigator.userAgentData-Aufrufen wechseln. Es gibt jedoch eine Übergangslösung.

UA-CH retrofill ist eine kleine Bibliothek, mit der Sie navigator.userAgent mit einem neuen String überschreiben können, der aus den angeforderten navigator.userAgentData-Werten erstellt wird.

Mit diesem Code wird beispielsweise ein User-Agent-String generiert, der zusätzlich den Hinweis „model“ enthält:

import { overrideUserAgentUsingClientHints } from './uach-retrofill.js';
overrideUserAgentUsingClientHints(['model'])
  .then(() => { console.log(navigator.userAgent); });

Der resultierende String enthält das Pixel 5-Modell, aber weiterhin die reduzierte 92.0.0.0, da der uaFullVersion-Hinweis nicht angefordert wurde:

Mozilla/5.0 (Linux; Android 10.0; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.0.0 Mobile Safari/537.36

Weitere Unterstützung

Wenn diese Strategien Ihren Anwendungsfall nicht abdecken, starten Sie bitte eine Diskussion im Repository „privacy-sandbox-dev-support“. Wir können dann gemeinsam nach einer Lösung für Ihr Problem suchen.

Foto von Ricardo Rocha auf Unsplash