Private State Tokens developer guide

In the past, third-party cookies have been used to store and convey information about a user's state, such as their sign-in status, information about the device they are using, or whether they are known and trusted. For example, whether the user has logged in with SSO, whether the user has a certain type of compatible device, or whether the user is known and trusted. With third-party cookie support being deprecated, many of these use cases will need to be supported by other means.

Private State Tokens offer a way to share information across the web, but in a privacy-preserving way through controls on the amount of data that can actually be shared.

Private State Tokens (formerly known as Trust Tokens) allow trust in a user's authenticity to be conveyed from one context to another while helping sites combat fraud and distinguish bots from real humans—without passive tracking.

This document outlines the technical details for implementing Private State Tokens (PST). For a more high-level outline, see the PST overview.

Learning flow for PST.
Learning process of PST: This process is composed of multiple steps, starting with understanding of the API and defining your own token strategy (more product or business related activities). After that, the technical phase is about implementing the demo in your local environment and then applying it to a real use-case.

How do Private State Tokens work?

The key relationship to understand in PST is between issuers and redeemers. Issuers and redeemers can be within the same company.

  • Issuers - These entities have some signal about a user (for example, whether that user is a bot or not) and embeds that signal into a token that is stored on the user device (more details in next sections).
  • Redeemers - These entities may not have a signal about a user but need to know something about them (for example, whether that user is a bot or not) and ask to redeem a token from the issuer to understand the trustworthiness of that user.

Every PST interaction requires issuers and redeemers to work together to share signals across the web. Those signals are coarse values that are not detailed enough to identify individuals.

Are Private State Tokens right for me?

Use cases of Private State Tokens.

Companies that are making trust decisions and want that information to be available across contexts may benefit from PSTs. For more on potential use-cases of PSTs, see our documentation on PST use cases.

Issue and redeem tokens

The PST implementation occurs in three phases:

  1. Issuing tokens
  2. Redeeming tokens
  3. Redemption record forwarding

In the first phase, tokens are issued to a browser (usually after some kind of validation). In the second phase, another entity will make a request to redeem the token that had been issued to read the value in that token. In the final phase, the redeeming party receives a redemption record (RR) with the value that was contained in the token. That redeeming party can then use that record as an attestation of that user for various purposes.

Basic flow of Private State Tokens.
Sequence diagram: The diagram shows a basic usage of PST in a real scenario where two websites want to exchange some signal about that specific Chrome instance. The two websites performs the issuance and redemption operations at different moments, being able to exchange a trusted signal between them.

Define your token strategy

To define your token strategy, you need to understand PST key concepts (tokens and redemption records), variables, behaviors and limitations to be able to think about their potential usage to your use case.

Tokens and redemption records: what's the relationship between them?

Each device can store up to 500 tokens per top-level website and issuer. Also, each token has metadata informing which key the issuer used to issue it. That information can be used to decide to redeem or not a token during the redeeming process. PST data is stored internally by the browser on the user's device and can only be accessed by the PST API.

When a token is redeemed, the Redemption Record (RR) is stored on the device. This storage acts as a cache for future redemptions. There is a limit of two tokens redemption every 48 hours, per device, page and issuer. New redemption calls will use cached RRs where possible, rather than causing a request to the issuer.

Relation between PST and RR.
  1. New tokens are issued (max 500 per issuer, site and device).
  2. All tokens are stored on-device token store (similar as cookie store).
  3. If no active RR is found, then new RRs can be generated after issuance (maximum of 2 every 48 hours).
  4. RRs are considered active until expiration and they will be used as a local cache.
  5. New redemption calls will hit local cache (no new RRs are generated).

After defining your use case, you must define your RR's lifespan carefully as this is going to define how many times you will be able to use them in your case.

Make sure you understand the following critical behaviors and variables before defining your strategy:

Variable / behavior Description Potential usage
Token key metadata Each token can be issued using one and only one cryptographic key and in PST there is a limitation of six keys per issuer. One potential way to use this variable is defining a range of trust to your tokens based on your cryptographic keys (for example, key 1 = high trust while key 6 = no trust).
Token expiration date Token expiration date is the same as key expiration date. Keys can be rotated at least every 60 days and all tokens issued with invalid keys are also considered invalid.
Token redemption rate limit There is a limit of two token redemptions per device and issuer every 48 hours. Depends on the estimated number of redemptions required by your use case every 48 hours.
Maximum number of issuers per top level origin Maximum number of issuers per top level origin is currently two. Carefully define the issuers of each page.
Tokens per issuer on a device Maximum number of tokens per issuer on a specific device is currently 500. Make sure to keep the number of tokens less than 500 per issuer.

Make sure to handle errors in your web page when trying to issue tokens.
Key commitments rotation Every PST issuer is required to expose an endpoint with key commitments that can be changed every 60 days and any rotation faster than that will be ignored. If your keys are going to expire in less than 60 days, it's mandatory to update your key commitments before that date to avoid disruption (see details).
Redemption record lifespan RR's lifespan can be defined in order to determine an expiration date. Since RRs are cached to avoid unnecessary new redemption calls to the issuer, this is important to make sure to have fresh enough redemption signals. Since there is a redemption rate-limit of two tokens every 48 hours, it's important to define your RR's lifespan to be able to execute redemption calls with success over at least this period of time (RR lifespan should be set accordingly). It is recommended to set this lifespan on the order of weeks.

Example scenarios

Scenario #1: RR lifespan is less than 24 hours (t=t) and redemption is performed multiple times during the 48-hour window.

Example scenario 1 of PST: small lifespan.
In this scenario, there is a 28-hour window where the user won't be able to redeem new tokens and all RRs will have expired.

Scenario #2: RR lifespan is 24 hours and redemption is performed multiple times during the 48-hour window.

Example scenario 2 of PST: 24 hour lifespan.
In this scenario since RR's lifespan is 24 hours, redemptions can be done during the whole 48 hours without any limitation.

Scenario #3: RR lifespan is 48 hours and redemption is performed multiple times during the 48 hours window.

Example scenario 3 of PST: 48 hour lifespan.
In this scenario since RR's lifespan is 48 hours, redemptions can be done during the whole 48 hours without any limitation.

Run the demo

Before adopting PST, we recommend getting set up with the demo first. To try out the PST demo , you will need to run Chrome with flags to enable the demo issuer key commitments (follow instructions available on the demo page).

PST demo screen.

By running this demo, your browser is using the demo issuer and redeemer servers to provide and consume tokens.

Technical considerations

The demo will run best if you implement the following steps:

  • Make sure you stop all Chrome instances before running Chrome with flags.
  • If you are running on a Windows machine, take a look into this guide on how to pass parameters to the Chrome executable binary.
  • Open Chrome DevTools under Applications > Storage > Private State Tokens while using the demo application to see the tokens issued/redeemed by the demo issuer.
Chrome DevTools screen showing PST.

Set up for adoption

Become an issuer

Issuers play a key role in PST. They assign values to the tokens to determine if a user is a bot or not. If you want to get started with PST as an issuer, you will need to register by completing the Issuer registration process.

To apply to become an issuer, the issuer website's operator must open a new issue on the GitHub repository using the "New PST Issuer" template. Follow the guidance on the repository to fill out the issue. Once an endpoint has been verified, it will be merged into this repository and Chrome server-side infrastructure will begin fetching those keys.

Issuer servers

Issuers and redeemers are the key actors for PST; servers and tokens are the key tools for PST. While we already have provided some details on tokens and in the Github documentation, we wanted to offer more details on PST servers. To get set up as an issuer of PST, you need to first set up an issuing server.

Deploy your environment: issuer servers

To implement the token issuer server you will need to build your own server side application exposing HTTP endpoints.

The issuer component is composed of two main modules: (1) the issuer server and (2) the token issuer.

Issuer server components.

As with all web-facing applications, we recommend an additional layer of protection to your issuer server.

  1. Issuer server: In our example implementation, our issuing server is a Node.js server that uses the Express framework to host the Issuer HTTP endpoints. You can check out sample code on GitHub.

  2. Token issuer: The issuer cryptographic component doesn't require any specific language but due to the performance requirements of this component, we're providing a C implementation as an example, which uses the Boring SSL library to manage tokens. You can find the issuer code example and more information about the installation on GitHub

  3. Keys: The token issuer component uses custom EC keys to encrypt tokens. These keys must be protected and stored in secure storage.

Technical requirements for issuer servers

As per the protocol, you will need to implement at least two HTTP endpoints in your issuer server:

  • Key-commitment (for example, /.well-known/private-state-token/key-commitment): This endpoint is where your encryption public key details will be available to browsers to confirm that your server is legitimate.
  • Token issuance (for example, /.well-known/private-state-token/issuance): The token issuing endpoint where all token requests will be handled. This endpoint will be the integration point for the token issuer component.

As mentioned previously, due to the expected high traffic this server will be potentially handling, we recommend you to deploy it using a scalable infrastructure (for example, in a cloud environment) to be able to adjust your backend based on a variable demand.

Send a call to the issuer server

Implement a website fetch call to your issuer stack in order to issue new tokens.

 // issuer request
    await fetch("/.well-known/private-state-token/issuance", {
      method: "POST",
      privateToken: {
        version: 1,
        operation: "token-request"
      }
    });

See a code example.

Redeemer servers

You will need to implement the token redemption service by building your own server-side application. This will allow you to read the tokens that an issuer sends. The following steps outline how to redeem tokens as well as how to read the redemption records that are associated with those tokens.

You can opt to run the issuer and the redeemer in the same server (or group of servers).

Redeemer server components.
PST demo components: These are the main components of the redeemer server. Redeemer server (Node.js Application) and Token redeemer (cryptographic component responsible for verifying signatures and tokens within the redemption process).

Technical requirements for redeemer servers

As per the protocol, you will need to implement at least two HTTP endpoints for your redeemer server:

  • /.well-known/private-state-token/redemption: endpoint where all token redemption will be handled. This endpoint will be where the token redeemer component will be integrated

Send a call to the redeemer server

To redeem tokens, you will need to implement a website fetch call to your redeemer stack in order to redeem tokens issued before.

    // redemption request
    await fetch("/.well-known/private-state-token/redemption", {
      method: "POST",
      privateToken: {
        version: 1,
        operation: "token-redemption",
        refreshPolicy: "none"
      }
    });

See code sample.

After redeeming a token, you can send the redemption record (RR) by doing another fetch call:

    // attach redemption records from the issuers to the request
    await fetch("<DESTINATION_RESOURCE>", {
      method: "POST",
      privateToken: {
        version: 1,
        operation: "send-redemption-record",
        issuers: [<ISSUER_DOMAIN>]
      }
    });

See code sample.

Deploy your implementation

To test your implementation, first navigate to the web page where the issuing call is made and confirm that the token(s) are created following your logic. Verify in your backend that the calls were made according to the specification. Then, navigate to the web page where the redeeming call is made and confirm that the RRs are created, following your logic.

Real world deployment

We recommend that you pick target websites that are part of your specific use case:

  • Small number of monthly visits (~ <1 million visits/month): You should begin by deploying the API to a small audience first
  • You own it and control it: If necessary you can quickly disable the implementation without complex approvals
  • No more than one issuer: To limit the amount of tokens in order to simplify testing.
  • No more than two redeemers: You need to simplify troubleshooting in case of problems.

Permissions policy

To function properly, the PST API must be available to the top-level page and any subresources that use the API.

The token-request operation is controlled by the private-state-token-issuance directive. The operations token-redemption and send-redemption-record are controlled by the private-state-token-redemption directive. By default, the allowlist for these directives is set to self. That means that the feature is only available to the top-level page (and same-origin iframes), and is not available to the cross-origin iframes without explicit delegation by the page.

You can opt out of PST token issuance or redemption for specific pages on your site by including private-state-token-issuance=() and private-state-token-redemption=() in the Permissions-Policy header for each page.

You can also use the Permissions-Policy header to control third-party access to PST. As parameters to the header origin list, use self and any origins you would like to allow access to the API. For example, to completely disable use of PST within all browsing contexts except for your own origin and https://example.com, set the following HTTP response headers:

Permissions-Policy:private-state-token-issuance=(self "https://example.com"),private-state-token-redemption=(self "https://example.com")

To enable the API for all cross-origin resources, set the origin list to *.

Learn how to control Privacy Sandbox features with Permissions Policy or delve deeper into understanding Permissions Policy.

Troubleshooting

You can inspect PSTs from the Chrome DevTools Network and Application tabs.

On the Network tab:

DevTools inspection for Network tab.
DevTools inspection for PST: Go to Network > Private state tokens to get all relevant information about tokens and issuers of one specific page.

On the Application tab:

DevTools inspection for Application tab.
DevTools inspection for PST: Go to Application > Private state tokens to get all relevant information about tokens and issuers of one specific page.

Read more about this DevTools integration.

Client best practices

If your website's critical functions depend on certain token issuers, prioritize them. Call hasPrivateToken(issuer) for these preferred issuers before loading any other scripts. This is crucial to prevent potential redemption failures.

The number of issuers per top-level is capped at two, and third-party scripts may also try to call hasPrivateToken(issuer) to prioritize their own preferred issuers. So, secure your essential issuers upfront to make sure your site operates as expected.

  // Prioritize your critical token issuer.
  document.hasPrivateToken('https://critical-issuer.example')
    .then(hasToken => {
      if (hasToken) {
        // Use the token or perform actions based on its availability.
      } else {
        // Handle the case where the token is not available.
      }
    });

  // Load third-party scripts or secure another token issuer (up to two in total).

Server best practices and troubleshooting

For your issuer and redeemer server to operate effectively, we recommend implementing the following best practices to ensure that you don't run into any access, security, logging, or traffic challenges for PST.

  • Your endpoints must apply strong cryptography by using TLS 1.3 or 1.2.
  • Your infrastructure must be ready to handle variable traffic volumes (including spikes).
  • Make sure your keys are protected and secure, aligned with your Access Control Policy, Key Management Strategy, and Business Continuity Plans.
  • Add observability metrics to your stack to make sure you will have visibility to understand usage, bottlenecks and performance issues after going to production.

More information

  1. Review developer docs:
    1. Begin by reading the overview to get up to speed with PST and its capabilities.
    2. Watch the PST intro video.
    3. Try the PST demo.
    4. Also read the API explainer to understand more details about it.
    5. Read more about the current spec of the API.
  2. Contribute to the conversation via GitHub issues or W3C calls.
  3. To better understand any of the terminology, review the Privacy Sandbox glossary.
  4. To learn more about Chrome concepts, such as 'origin trial' or 'Chrome flags', review the short videos and articles available from goo.gle/cc.