User-Agent Client-Hints, take 2
Tags: webdev, webperf, privacy
Published: 2021-03-12 13:49:46

I’ve written a [couple of post about User-Agent Client-Hints (UA-CH)](https://mpulp.mobi/tag/ua-ch/) before, and in specific how to [delegate UA-CH to third party sites or domains](https://mpulp.mobi/2020/05/27/delegate-user-agent-client-hints-to-3rd-parties/).

Delegating UA-CH is useful when you need other sites, domains or hostnames to receive the additional information. One example is if you’re using an image CDN to optimize images.

Since Chrome v84 the Chrome team has had a few set backs which has resulted in some changes. In addition, the feature policy header, for delegating the client hints to third parties, has [changed name to Permissions-Policy](https://github.com/w3c/webappsec-permissions-policy/blob/main/permissions-policy-explainer.md).

Based on my previous post, let’s see what’s changed, and learn how to delegate the UA-CH.

First, the JavaScript API is widely open and does not require any delegation or even opt-in. IMO this is a [privacy issue](https://mpulp.mobi/2020/05/27/user-agent-client-hints-security-concerns/), and [Apple seems to agree with me](https://github.com/WICG/ua-client-hints/issues/151) 🙂

## 1. Opt-in in to Receive User-Agent Client Hints

We still have to explicitly opt-in to receive the client hints in response headers. In previous implementations it was very confusing because the sec-ch- perfix was not required. Now, we’ll need to include that prefix like this:

```
Accept-CH: sec-ch-ua-platform,sec-ch-ua-arch,sec-ch-ua-model,sec-ch-ua-platform-version,sec-ch-ua-full-version`
```

## 2. Delegate UA-CH using Permissions Policy

UA-CH was launched with Chrome v84 just around the time when feature policy was renamed to permissions policy. Chrome v89 still supports the feature-policy header, but let’s move ahead with permissions-policy just to stay bleeding edge 🙂

The permissions policy is a structured header. Which makes it look a bit more complicated, but it’s really not.

```
permissions-policy: ch-ua-arch=("https://foo.bar.com"), ch-ua-model=("https://foo.bar.com"), ch-ua-platform=("https://foo.bar.com"), ch-ua-platform-version=("https://foo.bar.com"), ch-ua-full-version=("https://foo.bar.com")
```

Last time I noted a little caveat here, about the header names. Names are the same, but still different from the header names we used to opt-in to receive UA-CH above. Difference now, is that we don’t use the sec- prefix in the permission policy.

## 3. Read the UA-CH on your 3rd party resource

If we’ve done everything correct, we should now receive the UA-CH headers on our 3rd party. This part has not changed since Chrome v84:

```
sec-ch-ua-full-version: "89.0.4389.82"
sec-ch-ua-arch: "x86"
sec-ch-ua-platform: "macOS"
sec-ch-ua-platform-version: "11_2_3"
sec-ch-ua-model: ""
sec-ch-ua-mobile: ?0
sec-ch-ua: "Google Chrome";v="89", "Chromium";v="89", ";Not A Brand";v="99"
```

## Try it out

I’ve updated my little glitch to reflect the changes: [https://glen-wistful-protoceratops.glitch.me/](https://glen-wistful-protoceratops.glitch.me/)

{% glitch glen-wistful-protoceratops %}

Here’s the [“official” demo](https://user-agent-client-hints.glitch.me/). However, this does not demo the delegation to other domains or third parties.