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 wichtige Passive-Fingerprinting-Oberfläche in Browsern und außerdem schwer zu verarbeiten. 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, um die Daten in einem nutzerfreundlichen Format zurückzugeben.

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 sich 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?

Die Standard-User-Agent-Client-Hints umfassen:

  • 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 User-Agent-Anfrageheader auf dem Server verwenden und Ihre Anforderungen an diese Daten auf Ihrer gesamten Website relativ einheitlich 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 einer Stelle konfigurieren müssen. Sie können sie beispielsweise in Ihrer Webserverkonfiguration einfügen, wenn Sie dort bereits Header hinzufügen, in Ihrer Hostingkonfiguration oder in der Top-Level-Konfiguration des Frameworks oder der Plattform, die Sie für Ihre Website verwenden.

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

Browser oder andere Clients können unterschiedliche Standardhinweise bereitstellen. Daher sollten Sie alles angeben, was Sie benötigen, auch wenn es standardmäßig bereitgestellt wird.

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

⬇️ Antwortheader

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

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

⬇️ Antwortheader

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 das Parsen des User-Agent-Headers zurückgreifen, falls er nicht verfügbar ist.

Strategie: Hinweise an ursprungsübergreifende Anfragen weitergeben

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 finden Sie im Entwurf der Client-Hints-Infrastruktur.

⬇️ 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 anstelle statisch auf der gesamten Website anfordern. Das ist zwar etwas aufwendiger, aber wenn Sie bereits unterschiedliche Header pro Route festgelegt haben, ist dies eine gute Lösung.

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 Standard-Hinweise umfassen den Browsernamen mit der Hauptversion, die Plattform und den Indikator 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]

⬇️ Antwortheader

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.

Für Situationen, in denen Sie wirklich zusätzliche Hinweise beim ersten Laden der Seite benötigen, wird im Vorschlag zur Zuverlässigkeit von Clienthinweisen beschrieben, wie Sie Hinweise in den Einstellungen auf Verbindungsebene angeben. Dazu wird die Erweiterung Application-Layer Protocol Settings(ALPS) für TLS 1.3 verwendet, um diese frühzeitige Weitergabe von Hinweisen für 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 Code von Drittanbietern, 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 aber 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