Esegui la migrazione ai client hint dello user agent

Strategie per eseguire la migrazione del tuo sito dal base della stringa user agent ai nuovi client hint user agent.

La stringa dello user agent è una superficie di fingerprinting passiva significativa nei browser, oltre a essere difficile da elaborare. Tuttavia, esistono vari motivi validi per raccogliere ed elaborare i dati degli user agent, quindi serve un percorso per una soluzione migliore. I client hint user agent offrono sia un modo esplicito per dichiarare la necessità di dati degli user agent sia metodi per restituirli in un formato di facile utilizzo.

Questo articolo illustra come verificare l'accesso ai dati degli user agent ed eseguire la migrazione dell'utilizzo delle stringhe dello user agent ai client hint user agent.

Controlla la raccolta e l'utilizzo dei dati degli user agent

Come per qualsiasi forma di raccolta dei dati, è necessario sempre comprendere il motivo per cui vengono raccolti. Il primo passaggio, indipendentemente dal fatto che tu esegua o meno un'azione, è capire dove e perché utilizzi i dati degli user agent.

Se non sai se o dove vengono utilizzati i dati dello user agent, valuta la possibilità di cercare nel codice frontend navigator.userAgent e nel codice di backend per l'utilizzo dell'intestazione HTTP User-Agent. Dovresti inoltre controllare il codice front-end per verificare l'utilizzo di funzionalità già deprecate, come navigator.platform e navigator.appVersion.

Da un punto di vista funzionale, pensa a qualsiasi punto del codice in cui stai registrando o elaborando:

  • Nome o versione del browser
  • Nome o versione del sistema operativo
  • Marca o modello del dispositivo
  • Tipo di CPU, architettura o bit (ad esempio, 64 bit)

È inoltre probabile che tu stia utilizzando una libreria o un servizio di terze parti per elaborare lo user-agent. In questo caso, controlla se si stanno aggiornando per supportare i client hint user agent.

Utilizzi solo dati user agent di base?

L'insieme predefinito di Client hint user agent include:

  • Sec-CH-UA: nome del browser e versione principale/significativa
  • Sec-CH-UA-Mobile: valore booleano che indica un dispositivo mobile
  • Sec-CH-UA-Platform: nome del sistema operativo
    • Tieni presente che questa modifica è stata aggiornata nelle specifiche e verrà riflessa a breve in Chrome e in altri browser basati su Chromium.

Anche la versione ridotta della stringa user agent proposta conserverà queste informazioni di base in modo compatibile con le versioni precedenti. Ad esempio, invece di Chrome/90.0.4430.85, la stringa includerà Chrome/90.0.0.0.

Se controlli solo il nome del browser, la versione principale o il sistema operativo nella stringa dello user agent, il codice continuerà a funzionare, anche se probabilmente visualizzerai avvisi sul ritiro.

Anche se puoi e devi eseguire la migrazione ai client hint user agent, potresti dover rispettare dei vincoli in termini di codice o risorse. La riduzione delle informazioni nella stringa dello user agent in questo modo compatibile con le versioni precedenti ha lo scopo di garantire che, sebbene il codice esistente riceva informazioni meno dettagliate, debba conservare la funzionalità di base.

Strategia: API JavaScript lato client on demand

Se al momento utilizzi navigator.userAgent, devi passare alla preferenza navigator.userAgentData prima di tornare all'analisi della stringa dello user agent.

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

Se stai controllando i dispositivi mobili o i computer, utilizza il valore booleano mobile:

const isMobile = navigator.userAgentData.mobile;

userAgentData.brands è un array di oggetti con proprietà brand e version in cui il browser può elencare la compatibilità con quei brand. Puoi accedervi direttamente come array o utilizzare una chiamata some() per verificare se è presente una voce specifica:

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
}

Se hai bisogno di uno dei valori user agent più dettagliati e ad alta entropia, dovrai specificarlo e controllare il risultato nel valore Promise restituito:

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

Ti consigliamo di utilizzare questa strategia anche se vuoi passare dall'elaborazione lato server all'elaborazione lato client. L'API JavaScript non richiede l'accesso alle intestazioni delle richieste HTTP, pertanto i valori dello user agent possono essere richiesti in qualsiasi momento.

Strategia: intestazione lato server statica

Se utilizzi l'intestazione della richiesta User-Agent sul server e le tue esigenze relative a questi dati sono relativamente coerenti in tutto il sito, puoi specificare i suggerimenti client desiderati come insieme statico nelle risposte. Si tratta di un approccio relativamente semplice poiché in genere è sufficiente configurarlo in una sola posizione. Ad esempio, potrebbe trovarsi nella configurazione del server web se aggiungi già intestazioni, nella configurazione di hosting o nella configurazione di primo livello del framework o della piattaforma che utilizzi per il tuo sito.

Valuta questa strategia se stai trasformando o personalizzando le risposte pubblicate in base ai dati dello user agent.

I browser o altri client possono scegliere di fornire suggerimenti predefiniti diversi, quindi è buona norma specificare tutto ciò di cui hai bisogno, anche se in genere viene fornito per impostazione predefinita.

Ad esempio, le impostazioni predefinite attuali di Chrome sono rappresentate come segue:

⬇️ Intestazioni delle risposte

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

Se vuoi ricevere anche il modello del dispositivo nelle risposte, invia:

⬇️ Intestazioni delle risposte

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

Durante l'elaborazione sul lato server, devi prima controllare se l'intestazione Sec-CH-UA desiderata è stata inviata e poi utilizzare l'analisi delle intestazioni User-Agent, se non è disponibile.

Strategia: delega di suggerimenti alle richieste multiorigine

Se richiedi l'invio di sottorisorse multiorigine o tra siti che richiedono l'invio di client hint user agent per le richieste, dovrai specificare esplicitamente i suggerimenti desiderati utilizzando un criterio di autorizzazione.

Ad esempio, supponiamo che https://blog.site ospiti risorse su https://cdn.site, che possono restituire risorse ottimizzate per un dispositivo specifico. https://blog.site può chiedere il suggerimento Sec-CH-UA-Model, ma deve delegarlo esplicitamente a https://cdn.site utilizzando l'intestazione Permissions-Policy. L'elenco dei suggerimenti controllati da criteri è disponibile nella bozza Infrastruttura Suggerimenti per client

⬇️ Risposta da parte di blog.site che delega il suggerimento

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

⬆️ La richiesta alle sottorisorse su cdn.site include il suggerimento delegato

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

Puoi specificare più suggerimenti per più origini e non solo dall'intervallo ch-ua:

⬇️ Risposta da blog.site che delega più suggerimenti a più origini

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")

Strategia: delega di suggerimenti agli iframe

Gli iframe multiorigine funzionano in modo simile alle risorse multiorigine, ma devi specificare i suggerimenti che vuoi delegare nell'attributo allow.

⬇️ Risposta da blog.site

Accept-CH: Sec-CH-UA-Model

↪️ HTML per blog.site

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

⬆️ Richiesta a widget.site

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

L'attributo allow nell'iframe sostituirà qualsiasi intestazione Accept-CH che widget.site potrebbe inviarsi, quindi assicurati di aver specificato tutto ciò di cui il sito ha bisogno per l'iframe.

Strategia: suggerimenti dinamici lato server

Se hai bisogno di una selezione più ampia di suggerimenti per parti specifiche del percorso dell'utente rispetto al resto del sito, puoi scegliere di richiedere questi suggerimenti on demand anziché in modo statico nell'intero sito. È più complesso da gestire, ma se hai già impostato intestazioni diverse in base alle route potrebbe essere fattibile.

Qui è importante ricordare che ogni istanza dell'intestazione Accept-CH sovrascriverà di fatto l'insieme esistente. Quindi, se imposti dinamicamente l'intestazione, ogni pagina deve richiedere l'insieme completo di suggerimenti richiesti.

Ad esempio, sul tuo sito potresti avere una sezione in cui fornire icone e controlli corrispondenti al sistema operativo dell'utente. Per questo, potresti voler eseguire il pull di Sec-CH-UA-Platform-Version anche per pubblicare le sottorisorse appropriate.

⬇️ Intestazioni di risposta per /blog

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

⬇️ Intestazioni di risposta per /app

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

Strategia: suggerimenti lato server richiesti alla prima richiesta

Potrebbero verificarsi casi in cui hai bisogno di un set di suggerimenti superiore all'insieme predefinito di suggerimenti nella prima richiesta, ma è probabile che ciò sia raro, quindi assicurati di aver esaminato il ragionamento.

La prima richiesta indica in realtà la prima richiesta di primo livello per quell'origine inviata in quella sessione di navigazione. L'insieme di suggerimenti predefinito include il nome del browser con la versione principale, la piattaforma e l'indicatore dei dispositivi mobili. La domanda che dovresti porti qui è: hai bisogno di dati estesi al caricamento iniziale della pagina?

Per ulteriori suggerimenti sulla prima richiesta, sono disponibili due opzioni. Innanzitutto, puoi usare l'intestazione Critical-CH. Il formato è uguale a quello di Accept-CH, ma indica al browser che deve ritentare immediatamente la richiesta se la prima è stata inviata senza il suggerimento critico.

⬆️ Richiesta iniziale

[With default headers]

⬇️ Intestazioni delle risposte

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

🔃 Il browser riprova la richiesta iniziale con l'intestazione aggiuntiva

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

Ciò comporterà l'overhead del nuovo tentativo alla prima richiesta, ma il costo di implementazione è relativamente basso. Invia l'intestazione aggiuntiva e il browser farà il resto.

Per le situazioni in cui hai davvero bisogno di suggerimenti aggiuntivi al primo caricamento della pagina, la proposta sull'affidabilità dei suggerimenti dei clienti stabilisce un percorso per specificare i suggerimenti nelle impostazioni a livello di connessione. Questa funzionalità utilizza l'estensione ALPS(Application- Layer Protocol) a TLS 1.3 per consentire il passaggio anticipato di suggerimenti sulle connessioni HTTP/2 e HTTP/3. Questa è ancora una fase iniziale, ma se gestisci attivamente le tue impostazioni TLS e di connessione, questo è il momento ideale per dare il tuo contributo.

Strategia: supporto precedente

Il tuo sito potrebbe contenere codice precedente o di terze parti che dipende da navigator.userAgent, incluse parti della stringa dello user agent che verranno ridotte. A lungo termine, dovresti pianificare di passare alle chiamate navigator.userAgentData equivalenti, ma esiste una soluzione provvisoria.

UA-CH retrofill è una piccola libreria che ti consente di sovrascrivere navigator.userAgent con una nuova stringa creata con i valori navigator.userAgentData richiesti.

Ad esempio, questo codice genera una stringa user agent che include anche il suggerimento "model":

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

La stringa risultante mostrerà il modello Pixel 5, ma continuerà a mostrare il valore 92.0.0.0 ridotto poiché non è stato richiesto il suggerimento uaFullVersion:

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

Ulteriore assistenza

Se queste strategie non riguardano il tuo caso d'uso, avvia una Discussione nel repository privacy-sandbox-dev-support per consentirci di esaminare il problema insieme.

Foto di Ricardo Rocha su Unsplash