Esegui la migrazione ai client hint dello user agent

Strategie per eseguire la migrazione del sito dall'utilizzo della stringa user agent ai nuovi client hint dello user agent.

La stringa dello user agent è una superficie di fingerprinting passiva significativa nei browser, oltre a essere difficile da elaborare. Tuttavia, esistono tutti i tipi di motivi validi per la raccolta e l'elaborazione dei dati degli user agent, quindi ciò che serve è un percorso per una soluzione migliore. I client hint dello user agent forniscono un modo esplicito per dichiarare la tua necessità dei dati dello user agent e dei metodi per restituire i dati in un formato facile da usare.

Questo articolo illustra il controllo dell'accesso ai dati dello user agent e la migrazione dell'utilizzo delle stringhe dello user agent ai client hint dello user agent.

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

Come per qualsiasi forma di raccolta dei dati, devi sempre conoscere il motivo per cui li stai raccogliendo. Il primo passaggio, indipendentemente dal fatto che tu intraprenda o meno un'azione, è capire dove e perché utilizzi i dati dello user agent.

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

Da un punto di vista funzionale, pensa al 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 bitness (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 vengono aggiornati per supportare i client hint dello user agent.

Stai utilizzando solo dati user agent di base?

L'insieme predefinito di client hint dello 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 è stato aggiornato nella specifica e verrà riflesso 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 includerebbe Chrome/90.0.0.0.

Se stai controllando solo la stringa dello user agent per il nome del browser, la versione principale o il sistema operativo, il codice continuerà a funzionare anche se è probabile che vengano visualizzati avvisi di deprecazione.

Sebbene sia possibile e necessario eseguire la migrazione ai client hint dello user agent, è possibile che esistano vincoli di codice o risorse legacy che impediscono questo problema. 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, continui a mantenere la funzionalità di base.

Strategia: API JavaScript lato client on demand

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

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

Se stai cercando un dispositivo mobile o un 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 oppure 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 dello user agent più dettagliati e con alta entropia, dovrai specificarlo e verificare il risultato nel valore Promise restituito:

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

Potresti voler utilizzare questa strategia anche se vuoi passare dall'elaborazione lato server a quella lato client. L'API JavaScript non richiede l'accesso alle intestazioni delle richieste HTTP, quindi 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 client hint desiderati come un insieme statico nelle risposte. Si tratta di un approccio relativamente semplice, poiché in genere è sufficiente configurarlo in una sola località. Ad esempio, potrebbe trovarsi nella configurazione del server web se vi aggiungi già intestazioni, nella configurazione di hosting o nella configurazione di primo livello del framework o della piattaforma che utilizzi per il tuo sito.

Prendi in considerazione questa strategia se stai trasformando o personalizzando le risposte fornite in base ai dati dello user agent.

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

Ad esempio, i valori predefiniti attuali per Chrome saranno rappresentati 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, devi inviare:

⬇️ 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 innanzitutto controllare se l'intestazione Sec-CH-UA desiderata è stata inviata, quindi utilizzare l'analisi dell'intestazione User-Agent se non è disponibile.

Strategia: delega dei suggerimenti alle richieste multiorigine

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

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ò richiedere il suggerimento Sec-CH-UA-Model, ma deve delegarlo esplicitamente a https://cdn.site utilizzando l'intestazione Permissions-Policy. L'elenco dei hint controllati tramite criteri è disponibile nella bozza dell'infrastruttura dei client hint.

⬇️ Risposta 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 di 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 dei 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 sostituisce qualsiasi intestazione Accept-CH che widget.site può inviare automaticamente, quindi assicurati di aver specificato tutto ciò di cui il sito ha bisogno per il sito 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 sull'intero sito. Questa operazione è più complessa da gestire, ma potrebbe essere fattibile se hai già impostato intestazioni diverse per ogni route.

È importante ricordare che ogni istanza dell'intestazione Accept-CH sovrascriverà in modo efficace il set esistente. Pertanto, se imposti l'intestazione in modo dinamico, ogni pagina deve richiedere l'insieme completo di suggerimenti richiesti.

Ad esempio, potresti avere una sezione del sito in cui vuoi fornire icone e controlli corrispondenti al sistema operativo dell'utente. A questo scopo, potresti anche voler eseguire il pull di Sec-CH-UA-Platform-Version per gestire le risorse secondarie appropriate.

⬇️ Intestazioni delle risposte per /blog

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

⬇️ Intestazioni delle risposte 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 più suggerimenti rispetto all'insieme predefinito di suggerimenti per la prima richiesta; tuttavia, si tratta di una situazione molto rara, quindi assicurati di aver esaminato il ragionamento.

Con la prima richiesta si intende in realtà la prima richiesta di primo livello per quell'origine inviata durante quella sessione di navigazione. L'insieme predefinito di suggerimenti include il nome del browser con versione principale, la piattaforma e l'indicatore del dispositivo mobile. La domanda da porti a questo punto è: Avete bisogno di dati estesi durante il caricamento iniziale della pagina?

Per ulteriori suggerimenti in merito alla prima richiesta, puoi scegliere tra due opzioni. Innanzitutto, puoi utilizzare l'intestazione Critical-CH. Viene preso lo stesso formato di Accept-CH, ma comunica al browser che deve immediatamente riprovare 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 tenta di nuovo la richiesta iniziale con l'intestazione aggiuntiva

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

Questo comporterà l'overhead del nuovo tentativo per la prima richiesta, ma il costo di implementazione è relativamente basso. Inviando l'intestazione aggiuntiva, il browser farà il resto.

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

Strategia: assistenza precedente

Sul tuo sito potrebbe essere presente codice precedente o di terze parti che dipende da navigator.userAgent, comprese parti della stringa user agent che verranno ridotte. Sul lungo termine, dovresti pianificare il passaggio alle chiamate navigator.userAgentData equivalenti, ma esiste una soluzione provvisoria.

Retrofill UA-CH è una piccola libreria che consente di sovrascrivere navigator.userAgent con una nuova stringa creata dai 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 mostra il modello Pixel 5, ma mostra comunque il 92.0.0.0 ridotto perché il suggerimento uaFullVersion non è stato richiesto:

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 coprono il tuo caso d'uso, avvia una Discussione in privacy-sandbox-dev-support repo e potremo esplorare il tuo problema insieme.

Foto di Ricardo Rocha su Unsplash