Origin Trials Framework Token Structure

Overview

The use of tokens is described fully in Origin Trials Framework Design Outline. Briefly, tokens are generated for a specific combination of origin and experimental feature, known as an origin trial. The origin must present the trial token when intending to use a feature, which is then verified by the browser. This document provides the details of token structure and validation.

Token Format

Trial tokens are base64-encoded binary structures, containing a signed JSON-encoded string, as shown in the diagram below:

 _____________________________________
| Token version number (1 byte)       |
|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|
| Public Key Signature (64 bytes)     |
|_____________________________________|
| Payload Length (4 bytes, big-endian)|
|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|
| Origin                              |
| Feature name     <=== Payload       |
| ...more               (JSON string) |
|_____________________________________|

Version (1 byte): This should be the byte 0x02 or 0x03 (the preferred version), representing version 2 and 3, which this document describes. Version 2 is supported from M51 and Version 3 is supported from M86. There is no correlation to browser version.

Signature: (64 bytes): Ed25519(private_key, signed_data)

Payload_length: (4 bytes): Big-endian unsigned 32-bit integer representing the size of the payload field, in bytes.

Payload: The payload is a JSON string, encoding a dictionary which should contain these keys:

  • origin
  • isSubdomain [Optional]
    • This key will often be omitted to minimize the size of the token
  • isThirdParty [Optional]
  • usage [Optional]
    • This key should only be specified if isThirdParty is true
  • feature
  • expiry

signed_data: This is the concatenation of the version, payload length and payload fields.

origin = scheme + “://” + host + “:” + port

isSubdomain = true|false. Indicates if the token should match all subdomains of the given origin. When the key is omitted, that is equivalent to specifying value = false.

isThirdParty = true|false. Indicates if the token should match third party origins. When the key is omitted, that is equivalent to specifying value = false.

usage = ""|“subset”. Indicates the usage restriction to be applied to the token. When the key is omitted, that is equivalent to specifying value = "".

scheme = the UTF-8 encoding of “https”|“http”|“chrome-extension”

host = the UTF-8 encoding of the hostname

port = the UTF-8 encoding of the port number in base-10 digits.

feature = A UTF-8 encoded string representing the name of an feature available for origin trials.

expiry = the UTC timestamp, as an integer number of seconds since the Unix epoch.

Samples

Regular Token on version 3

This is a typical token, which is used for one exact domain.

Origin: https://example.com/

Feature Name: “Frobulate”

Expiry Date: 2020-12-31 23:59:59 (1609459199)

Payload (83 characters)

{"origin": "https://example.com:443", "feature": "Frobulate", "expiry": 1609459199}

Signed Data: (88 bytes):

03 00 00 00 53 7b 22 6f 72 69 67 69 6e 22 3a 20 22 68 74 74 70 73 3a 2f 2f 65 78 61 6d 70 6c 65 2e 63 6f 6d 3a 34 34 33 22 2c 20 22 66 65 61 74 75 72 65 22 3a 20 22 46 72 6f 62 75 6c 61 74 65 22 2c 20 22 65 78 70 69 72 79 22 3a 20 31 36 30 39 34 35 39 31 39 39 7d

Signature: (Ed25519(private_key, data)) (64 bytes)

d6 13 93 95 8b 33 4b a1 5c f8 f6 38 4f dd 12 3f 26 11 d5 9b 71 63 af 0b 25 8c 35 d4 45 88 26 69 05 1b b2 9f 12 4c c7 58 bf 48 ee 69 45 3e d4 86 80 92 0d 38 9e a2 1f 6a 38 23 07 b1 cd b2 e7 0e

Complete Token: (152 bytes)

03 d6 13 93 95 8b 33 4b a1 5c f8 f6 38 4f dd 12 3f 26 11 d5 9b 71 63 af 0b 25 8c 35 d4 45 88 26 69 05 1b b2 9f 12 4c c7 58 bf 48 ee 69 45 3e d4 86 80 92 0d 38 9e a2 1f 6a 38 23 07 b1 cd b2 e7 0e 00 00 00 53 7b 22 6f 72 69 67 69 6e 22 3a 20 22 68 74 74 70 73 3a 2f 2f 65 78 61 6d 70 6c 65 2e 63 6f 6d 3a 34 34 33 22 2c 20 22 66 65 61 74 75 72 65 22 3a 20 22 46 72 6f 62 75 6c 61 74 65 22 2c 20 22 65 78 70 69 72 79 22 3a 20 31 36 30 39 34 35 39 31 39 39 7d

Trial token: (204 characters)

A9YTk5WLM0uhXPj2OE/dEj8mEdWbcWOvCyWMNdRFiCZpBRuynxJMx1i/SO5pRT7UhoCSDTieoh9qOCMHsc2y5w4AAABTeyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5IjogMTYwOTQ1OTE5OX0=

Meta Tag:

<meta http-equiv="origin-trial" content="A9YTk5WLM0uhXPj2OE/dEj8mEdWbcWOvCyWMNdRFiCZpBRuynxJMx1i/SO5pRT7UhoCSDTieoh9qOCMHsc2y5w4AAABTeyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5IjogMTYwOTQ1OTE5OX0=" />

Subdomain Token on version 3

This token is used for matching all subdomains of an origin (e.g. valid for *.example.com).

Origin: https://example.com/

Matches Subdomains: Yes

Feature Name: “Frobulate”

Expiry Date: 2020-12-31 23:59:59 (1609459199)

Payload (104 characters)

{"origin": "https://example.com:443", "isSubdomain": true, "feature": "Frobulate", "expiry": 1609459199}

Signed Data: (109 bytes):

 03 00 00 00 68 7b 22 6f 72 69 67 69 6e 22 3a 20 22 68 74 74 70 73 3a 2f 2f 65 78 61 6d 70 6c 65 2e 63 6f 6d 3a 34 34 33 22 2c 20 22 69 73 53 75 62 64 6f 6d 61 69 6e 22 3a 20 74 72 75 65 2c 20 22 66 65 61 74 75 72 65 22 3a 20 22 46 72 6f 62 75 6c 61 74 65 22 2c 20 22 65 78 70 69 72 79 22 3a 20 31 36 30 39 34 35 39 31 39 39 7d

Signature: (Ed25519(private_key, data)) (64 bytes)

31 e2 79 26 f7 35 71 d7 84 9d 73 bf 13 5c 99 47 91 df 9d 70 ce 55 f0 24 ae e9 60 cf 0c 08 57 cd 7a 7b e8 9d 98 b7 d2 44 b4 18 e2 96 52 57 88 c9 ab 6c ff 66 93 07 51 e8 88 29 8b 58 8b c6 e4 08

Complete Token: (173 bytes)

03 31 e2 79 26 f7 35 71 d7 84 9d 73 bf 13 5c 99 47 91 df 9d 70 ce 55 f0 24 ae e9 60 cf 0c 08 57 cd 7a 7b e8 9d 98 b7 d2 44 b4 18 e2 96 52 57 88 c9 ab 6c ff 66 93 07 51 e8 88 29 8b 58 8b c6 e4 08 00 00 00 68 7b 22 6f 72 69 67 69 6e 22 3a 20 22 68 74 74 70 73 3a 2f 2f 65 78 61 6d 70 6c 65 2e 63 6f 6d 3a 34 34 33 22 2c 20 22 69 73 53 75 62 64 6f 6d 61 69 6e 22 3a 20 74 72 75 65 2c 20 22 66 65 61 74 75 72 65 22 3a 20 22 46 72 6f 62 75 6c 61 74 65 22 2c 20 22 65 78 70 69 72 79 22 3a 20 31 36 30 39 34 35 39 31 39 39 7d


Trial token (232 characters):

AzHieSb3NXHXhJ1zvxNcmUeR351wzlXwJK7pYM8MCFfNenvonZi30kS0GOKWUleIyats/2aTB1HoiCmLWIvG5AgAAABoeyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLmNvbTo0NDMiLCAiaXNTdWJkb21haW4iOiB0cnVlLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5IjogMTYwOTQ1OTE5OX0=

Meta Tag:

<meta http-equiv="origin-trial" content="AzHieSb3NXHXhJ1zvxNcmUeR351wzlXwJK7pYM8MCFfNenvonZi30kS0GOKWUleIyats/2aTB1HoiCmLWIvG5AgAAABoeyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLmNvbTo0NDMiLCAiaXNTdWJkb21haW4iOiB0cnVlLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5IjogMTYwOTQ1OTE5OX0=" />

Third Party Token (only supported in Version 3)

This token is used for matching third party origins.

Origin: https://thirdparty.com/

Feature Name: “Frobulate”

Matches Third Party Origins: True

Expiry Date: 2020-12-31 23:59:59 (1609459199)

Payload (108 characters)

{"origin": "https://thirdparty.com:443", "feature": "Frobulate", "expiry": 1609459199, "isThirdParty": true}

Signed Data: (113 bytes):

03 00 00 00 6c 7b 22 6f 72 69 67 69 6e 22 3a 20 22 68 74 74 70 73 3a 2f 2f 74 68 69 72 64 70 61 72 74 79 2e 63 6f 6d 3a 34 34 33 22 2c 20 22 69 73 54 68 69 72 64 50 61 72 74 79 22 3a 20 74 72 75 65 2c 20 22 66 65 61 74 75 72 65 22 3a 20 22 46 72 6f 62 75 6c 61 74 65 22 2c 20 22 65 78 70 69 72 79 22 3a 20 31 36 30 39 34 35 39 31 39 39 7d

Signature: (Ed25519(private_key, data)) (64 bytes)

1f 14 b0 25 3d 11 40 51 8f c3 d9 1b 5e 3b 70 e3 bb 56 a4 7c e8 11 75 dd 34 ae eb 0d b0 46 a8 b1 cc 9f 9f 11 45 0b bc e4 22 99 7c 16 97 51 13 60 27 c0 64 c9 6f bc 0a a8 15 80 7c 1f 1a ec 64 0e

Complete Token: (177 bytes)

03 1f 14 b0 25 3d 11 40 51 8f c3 d9 1b 5e 3b 70 e3 bb 56 a4 7c e8 11 75 dd 34 ae eb 0d b0 46 a8 b1 cc 9f 9f 11 45 0b bc e4 22 99 7c 16 97 51 13 60 27 c0 64 c9 6f bc 0a a8 15 80 7c 1f 1a ec 64 0e 00 00 00 6c 7b 22 6f 72 69 67 69 6e 22 3a 20 22 68 74 74 70 73 3a 2f 2f 74 68 69 72 64 70 61 72 74 79 2e 63 6f 6d 3a 34 34 33 22 2c 20 22 69 73 54 68 69 72 64 50 61 72 74 79 22 3a 20 74 72 75 65 2c 20 22 66 65 61 74 75 72 65 22 3a 20 22 46 72 6f 62 75 6c 61 74 65 22 2c 20 22 65 78 70 69 72 79 22 3a 20 31 36 30 39 34 35 39 31 39 39 7d

Trial token: (236 characters)

Ax8UsCU9EUBRj8PZG147cOO7VqR86BF13TSu6w2wRqixzJ+fEUULvOQimXwWl1ETYCfAZMlvvAqoFYB8HxrsZA4AAABseyJvcmlnaW4iOiAiaHR0cHM6Ly90aGlyZHBhcnR5LmNvbTo0NDMiLCAiaXNUaGlyZFBhcnR5IjogdHJ1ZSwgImZlYXR1cmUiOiAiRnJvYnVsYXRlIiwgImV4cGlyeSI6IDE2MDk0NTkxOTl9

Meta Tag:

<meta http-equiv="origin-trial" content="Ax8UsCU9EUBRj8PZG147cOO7VqR86BF13TSu6w2wRqixzJ+fEUULvOQimXwWl1ETYCfAZMlvvAqoFYB8HxrsZA4AAABseyJvcmlnaW4iOiAiaHR0cHM6Ly90aGlyZHBhcnR5LmNvbTo0NDMiLCAiaXNUaGlyZFBhcnR5IjogdHJ1ZSwgImZlYXR1cmUiOiAiRnJvYnVsYXRlIiwgImV4cGlyeSI6IDE2MDk0NTkxOTl9" />

Third Party Token with alternative usage restriction (only supported in version 3)

This token is used for matching third party origins. It also contains instructions for using alternative usage restrictions.

Origin: https://thirdparty.com/

Feature Name: “Frobulate”

Matches Third Party Origins: True

Usage Restrictions: Subset

Expiry Date: 2020-12-31 23:59:59 (1609459199)

Payload (127 characters)

{"origin": "https://thirdparty.com:443", "feature": "Frobulate", "expiry": 1609459199, "isThirdParty": true, "usage": "subset"}

Signed Data: (132 bytes):

03 00 00 00 7f 7b 22 6f 72 69 67 69 6e 22 3a 20 22 68 74 74 70 73 3a 2f 2f 74 68 69 72 64 70 61 72 74 79 2e 63 6f 6d 3a 34 34 33 22 2c 20 22 69 73 54 68 69 72 64 50 61 72 74 79 22 3a 20 74 72 75 65 2c 20 22 75 73 61 67 65 22 3a 20 22 73 75 62 73 65 74 22 2c 20 22 66 65 61 74 75 72 65 22 3a 20 22 46 72 6f 62 75 6c 61 74 65 22 2c 20 22 65 78 70 69 72 79 22 3a 20 31 36 30 39 34 35 39 31 39 39 7d

Signature: (Ed25519(private_key, data)) (64 bytes)

31 2c ed 7c d0 1b 99 2d 58 5f e9 ba ba 12 53 94 73 c4 f1 1d 11 45 21 ab 05 ed 2f 68 48 b5 9a 09 53 46 e0 84 ac 1b b1 32 95 82 19 11 f7 91 87 49 f2 0d 4c 19 f1 c1 10 67 15 57 d8 18 92 e6 f0 05

Complete Token: (196 bytes)

03 31 2c ed 7c d0 1b 99 2d 58 5f e9 ba ba 12 53 94 73 c4 f1 1d 11 45 21 ab 05 ed 2f 68 48 b5 9a 09 53 46 e0 84 ac 1b b1 32 95 82 19 11 f7 91 87 49 f2 0d 4c 19 f1 c1 10 67 15 57 d8 18 92 e6 f0 05 00 00 00 7f 7b 22 6f 72 69 67 69 6e 22 3a 20 22 68 74 74 70 73 3a 2f 2f 74 68 69 72 64 70 61 72 74 79 2e 63 6f 6d 3a 34 34 33 22 2c 20 22 69 73 54 68 69 72 64 50 61 72 74 79 22 3a 20 74 72 75 65 2c 20 22 75 73 61 67 65 22 3a 20 22 73 75 62 73 65 74 22 2c 20 22 66 65 61 74 75 72 65 22 3a 20 22 46 72 6f 62 75 6c 61 74 65 22 2c 20 22 65 78 70 69 72 79 22 3a 20 31 36 30 39 34 35 39 31 39 39 7d

Trial token: (264 characters)

AzEs7XzQG5ktWF/puroSU5RzxPEdEUUhqwXtL2hItZoJU0bghKwbsTKVghkR95GHSfINTBnxwRBnFVfYGJLm8AUAAAB/eyJvcmlnaW4iOiAiaHR0cHM6Ly90aGlyZHBhcnR5LmNvbTo0NDMiLCAiaXNUaGlyZFBhcnR5IjogdHJ1ZSwgInVzYWdlIjogInN1YnNldCIsICJmZWF0dXJlIjogIkZyb2J1bGF0ZSIsICJleHBpcnkiOiAxNjA5NDU5MTk5fQ==

Meta Tag:

<meta http-equiv="origin-trial" content="AzEs7XzQG5ktWF/puroSU5RzxPEdEUUhqwXtL2hItZoJU0bghKwbsTKVghkR95GHSfINTBnxwRBnFVfYGJLm8AUAAAB/eyJvcmlnaW4iOiAiaHR0cHM6Ly90aGlyZHBhcnR5LmNvbTo0NDMiLCAiaXNUaGlyZFBhcnR5IjogdHJ1ZSwgInVzYWdlIjogInN1YnNldCIsICJmZWF0dXJlIjogIkZyb2J1bGF0ZSIsICJleHBpcnkiOiAxNjA5NDU5MTk5fQ==" />

Version 2 Tokens

Version 2 Tokens will have same payload for regular and subdomain tokens, the only difference is the first version byte becomes \x02.

Third party tokens are only supported in Version 3.

Obsolete Versions:

Version 1

This was the original specification, which was supported in Chrome M50, but not used to support any actual experiments in that release.