{
  "about": "Identity tokens for a logged-in user, as every library of ours signs them (packages/), and as Help reads them (identity.rs). HS256. The header is {\"alg\":\"HS256\",\"typ\":\"JWT\"} with \"kid\" after them when one is given. The claims are sub (the id, trimmed, as text), email when given (trimmed), iat (now), exp (now + expires_in), jti when the token is used once, and user (the facts) when there are any, its names in byte order; written as JSON with no spaces, with / and letters beyond ASCII as they are. Each part is base64url with no padding, and the signature is HMAC-SHA256 under the secret's own text. A library makes its own jti (16 random bytes, base64url) and takes now from its clock: each vector names both. `invalid` is what a library refuses before signing, by the code it refuses with. The secrets open nothing. An invalid case is signed with the test secret for 600 seconds unless it names its own.",
  "tokens": [
    {
      "name": "a logged-in user with only an id, once",
      "secret": "hsk_test_example-secret-that-opens-nothing",
      "now": 1790000000,
      "user": {
        "id": "42"
      },
      "expires_in": 600,
      "once": true,
      "jti": "abc",
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiIsImlhdCI6MTc5MDAwMDAwMCwiZXhwIjoxNzkwMDAwNjAwLCJqdGkiOiJhYmMifQ.165LXa4ZiioHCpwnb3dCyay_Ga9UDLf16LtRdAOK0AI"
    },
    {
      "name": "an id given as a number is signed as text",
      "secret": "hsk_test_example-secret-that-opens-nothing",
      "now": 1790000000,
      "user": {
        "id": 42
      },
      "expires_in": 600,
      "once": true,
      "jti": "0123456789abcdefghij-_",
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiIsImlhdCI6MTc5MDAwMDAwMCwiZXhwIjoxNzkwMDAwNjAwLCJqdGkiOiIwMTIzNDU2Nzg5YWJjZGVmZ2hpai1fIn0.ImNJBzHYyZsy206Oa9iFoTQHtgg24n0DM361l1naqEI"
    },
    {
      "name": "an email and facts, the facts by their names in order, with the secret's id",
      "secret": "hsk_live_example-secret-that-opens-nothing",
      "kid": "ik_0a1b2c3d",
      "now": 1790000300,
      "user": {
        "id": "user_7",
        "email": "ada@example.com",
        "facts": {
          "plan": "gold",
          "seats": 3,
          "trial": false,
          "company": "Zürich & Co / Ltd"
        }
      },
      "expires_in": 600,
      "once": true,
      "jti": "Ze9F2kq1",
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImlrXzBhMWIyYzNkIn0.eyJzdWIiOiJ1c2VyXzciLCJlbWFpbCI6ImFkYUBleGFtcGxlLmNvbSIsImlhdCI6MTc5MDAwMDMwMCwiZXhwIjoxNzkwMDAwOTAwLCJqdGkiOiJaZTlGMmtxMSIsInVzZXIiOnsiY29tcGFueSI6IlrDvHJpY2ggJiBDbyAvIEx0ZCIsInBsYW4iOiJnb2xkIiwic2VhdHMiOjMsInRyaWFsIjpmYWxzZX19.JkG5Nqu6NNO8pF63iCyHMpy7iMx7wyYY8a8WW9OclwM"
    },
    {
      "name": "a token that may be used more than once has no jti",
      "secret": "hsk_test_example-secret-that-opens-nothing",
      "now": 1790000000,
      "user": {
        "id": "  42  "
      },
      "expires_in": 86400,
      "once": false,
      "jti": null,
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI0MiIsImlhdCI6MTc5MDAwMDAwMCwiZXhwIjoxNzkwMDg2NDAwfQ.DurQorXcSBmCma8lIjpM2JHf9OQT1o9cPcMFu4TcIl0"
    },
    {
      "name": "text is written as it is: quotes, a backslash and letters beyond ASCII",
      "secret": "hsk_live_example-secret-that-opens-nothing",
      "now": 1790000000,
      "user": {
        "id": "o'brien \"ob\" \\ ñ",
        "facts": {
          "10": "ten",
          "9": "nine",
          "a_b": true
        }
      },
      "expires_in": 60,
      "once": true,
      "jti": "j",
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJvJ2JyaWVuIFwib2JcIiBcXCDDsSIsImlhdCI6MTc5MDAwMDAwMCwiZXhwIjoxNzkwMDAwMDYwLCJqdGkiOiJqIiwidXNlciI6eyIxMCI6InRlbiIsIjkiOiJuaW5lIiwiYV9iIjp0cnVlfX0.bWWIWbwZ-3y31GamA3uiOKlHIHLl5PHLsmilISNVrdw"
    }
  ],
  "invalid": [
    {
      "name": "no id",
      "user": {
        "id": "  "
      },
      "error": "bad_user"
    },
    {
      "name": "an id longer than 128 characters",
      "user": {
        "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      },
      "error": "bad_user"
    },
    {
      "name": "an id that is not text or a whole number",
      "user": {
        "id": 4.5
      },
      "error": "bad_user"
    },
    {
      "name": "an id with a control character",
      "user": {
        "id": "4\n2"
      },
      "error": "bad_user"
    },
    {
      "name": "an email that is not an address",
      "user": {
        "id": "42",
        "email": "not an address"
      },
      "error": "bad_email"
    },
    {
      "name": "eleven facts",
      "user": {
        "id": "42",
        "facts": {
          "k0": 0,
          "k1": 1,
          "k2": 2,
          "k3": 3,
          "k4": 4,
          "k5": 5,
          "k6": 6,
          "k7": 7,
          "k8": 8,
          "k9": 9,
          "k10": 10
        }
      },
      "error": "bad_facts"
    },
    {
      "name": "a fact named with a capital",
      "user": {
        "id": "42",
        "facts": {
          "Plan": "gold"
        }
      },
      "error": "bad_facts"
    },
    {
      "name": "a fact name longer than 40",
      "user": {
        "id": "42",
        "facts": {
          "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "x"
        }
      },
      "error": "bad_facts"
    },
    {
      "name": "a fact longer than 100 characters",
      "user": {
        "id": "42",
        "facts": {
          "plan": "ééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé"
        }
      },
      "error": "bad_facts"
    },
    {
      "name": "a fact that is a list",
      "user": {
        "id": "42",
        "facts": {
          "plan": [
            "gold"
          ]
        }
      },
      "error": "bad_facts"
    },
    {
      "name": "a fact with a line break",
      "user": {
        "id": "42",
        "facts": {
          "plan": "gold\nsilver"
        }
      },
      "error": "bad_facts"
    },
    {
      "name": "a fact that is empty",
      "user": {
        "id": "42",
        "facts": {
          "plan": ""
        }
      },
      "error": "bad_facts"
    },
    {
      "name": "more than a day",
      "user": {
        "id": "42"
      },
      "expires_in": 86401,
      "error": "bad_expiry"
    },
    {
      "name": "no time at all",
      "user": {
        "id": "42"
      },
      "expires_in": 0,
      "error": "bad_expiry"
    },
    {
      "name": "a publishable key in place of the secret",
      "user": {
        "id": "42"
      },
      "secret": "pk_live_abc",
      "error": "bad_secret"
    },
    {
      "name": "no secret",
      "user": {
        "id": "42"
      },
      "secret": "",
      "error": "bad_secret"
    }
  ]
}
