Private State Tokens API: Anonymous User Validation

The Private State Tokens API is a privacy-focused web platform API designed to combat fraud and verify legitimate human users across different websites without using cross-site tracking or user fingerprinting. By utilizing cryptographic blind signatures, the API enables a website that has established trust with a user to issue tokens that the user can later redeem on other sites. This article explains what the Private State Tokens API is, why it was created, how its token lifecycle functions, and how JavaScript is used to issue and redeem tokens anonymously.


What Is the Private State Tokens API?

Part of the Google-led Privacy Sandbox initiative, the Private State Tokens API (formerly known as Trust Tokens API) offers an alternative to third-party cookies and intrusive fingerprinting techniques historically used for anti-fraud measures.

Traditional anti-abuse mechanisms often track a user’s browsing history across multiple domains to determine whether they are a bot or a real human. The Private State Tokens API solves this problem by allowing trust to be shared across contexts without conveying identity. It confirms that a user is a legitimate human while guaranteeing that their browsing habits remain completely private and unlinkable between the issuing site and the redeeming site.


Core Mechanics: Blind Signatures and Anonymity

The cornerstone of the Private State Tokens API is a cryptographic technique called Blind Signatures.

  1. Blinding: When a user requests a token from a trusted site (the Issuer), the browser creates cryptographic data and “blinds” (masks) it before sending it.
  2. Signing: The Issuer verifies the user (for instance, via a CAPTCHA, account authentication, or activity metrics) and signs the masked data with a private key without ever seeing the underlying token value.
  3. Unblinding: The browser receives the signed, blinded token, unblinds it locally, and stores the valid signature.
  4. Redemption: When visiting a separate site (the Redeemer), the browser provides the token. The Redeemer or Issuer can verify that the signature is valid without being able to correlate it to the specific issuance event.

Because the token contents are blinded during signing, the issuer cannot match the token issued on Site A with the token redeemed on Site B.


Key Roles in the Token Lifecycle


How JavaScript Implements Private State Tokens

The API integrates natively into JavaScript’s fetch() API and HTML elements using the privateToken operation parameter.

1. Issuing a Token

When a site establishes that a visitor is human, JavaScript requests a token issuance from an approved issuer endpoint:

async function requestPrivateToken() {
  try {
    const response = await fetch("https://issuer.example/issue-token", {
      privateToken: {
        version: 1,
        operation: "token-request"
      }
    });

    if (response.ok) {
      console.log("Private State Token issued and stored securely in the browser.");
    }
  } catch (error) {
    console.error("Token issuance failed:", error);
  }
}

The browser handles cryptographic key generation and stores the resulting blinded token in a secure partition associated with that issuer.

2. Redeeming a Token

When the user visits a third-party site that needs verification, the site requests a Redemption Record (RR) using JavaScript:

async function redeemPrivateToken() {
  try {
    const response = await fetch("https://issuer.example/redeem-token", {
      privateToken: {
        version: 1,
        operation: "token-redemption",
        refreshPolicy: "none"
      }
    });

    if (response.ok) {
      console.log("Token redeemed successfully. Redemption record stored.");
    }
  } catch (error) {
    console.error("Token redemption failed:", error);
  }
}

Once redeemed, a Redemption Record is cached in the browser for that domain.

3. Sending the Redemption Record

To complete the validation, the site forwards the Redemption Record to its own backend server to confirm authenticity:

async function sendValidationRecord() {
  const response = await fetch("https://relyingsite.example/process-action", {
    privateToken: {
      version: 1,
      operation: "send-redemption-record",
      issuers: ["https://issuer.example"]
    }
  });

  const result = await response.json();
  if (result.humanVerified) {
    // Proceed with restricted action
  }
}

The relying server verifies the cryptographic signature on the Redemption Record using the issuer’s public key, confirming the visitor was verified by the issuer without ever learning who the visitor is.


Key Privacy Safeguards