A JSON Web Token (JWT) is defined in three parts:
Header: contains the definition and format of the JWT and JWS;
Payload/Claims Set: contains additional information, such as listener ID, user tags, etc.;
Signature: cryptographic signature (i.e., hash) of the Header and Payload, using the algorithm specified in the Header.
In JWT, the individual parts are expressed in a compact JSON format, encoded using Base64URL, and concatenated with periods (".").
The encoding used is Base64URL, as defined in https://tools.ietf.org/html/rfc4648#section-5, and not plain old Base64. The difference is mostly that two characters were replaced by URL-safe characters, and the final padding ("=") is removed.
There are plenty of examples on the Web on how to do this in various languages – the exercise is left to the reader. For sample/development needs, you can use the openssl command to encode Base64URL with the following command line:echo -n "Data to encode" | openssl enc -a -A | tr -d '=' | tr '/+' '_-'
JWT Protected Header
Key | Description | Value | Required | Notes |
---|---|---|---|---|
typ | Type | JWT | ✅ |
|
alg | Algorithm | HS256 | ✅ | Identifies signature algorithm as HMAC using SHA-256 |
kid | Key ID | Key ID | ✅ | The Secret Key's ID, provided by Triton |
JWT Header Example
{"typ":"JWT","alg":"HS256","kid":"a1b2c3d4e5"}
Encoded with Base64URL:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6ImExYjJjM2Q0ZTUifQ
JWT Payload (Claims Set)
Application-specific parameters are defined in the user guides for each application. The parameters below are common to all applications:
Key | Description | Value | Required | Notes |
---|---|---|---|---|
iat | Issued At | Unix timestamp when the token was created. | ✅ | The service uses this to cap the expiration time of the token. |
exp | Expiration | Unix timestamp when the token expires. |
| If provided, this allows the token to expire before the maximum allowed time defined by the service. (The default service expiry is 60 seconds.) |
iss | Issuer | Identifier of the token-generating component (e.g., player, back-end, etc.) |
| This identifier should be short. |
aud | Audience | td |
| Used to make sure we don't interpret a token that's not aimed at us. |
sub | Subject | User ID (from authentication) |
| Not always applicable; for example, if token was generated by the player rather than an authentication system. If a user ID is available, it should be provided. |
In the example below, the application-specific parameter "td-reg"
is provided:
JWT Claims Set Example
{"iss":"pdvy","sub":"foo@bar.com","iat":1429802716,"td-reg":true}
Encoded with Base64URL:eyJpc3MiOiJwZHZ5Iiwic3ViIjoiZm9vQGJhci5jb20iLCJpYXQiOjE0Mjk4MDI3MTYsInRkLXJlZyI6dHJ1ZX0
JWS Signature
Standard HS256 signature, as defined in JWS RFC.
Triton will generate and provide the HMAC secret key.
Secret keys are provided on a broadcaster-wide basis (i.e., a key is valid for all stations that are part of the broadcaster).
HMAC key will be provided to the issuer in a secure manner (TBD).
The HMAC key is what makes this solution secure – it is very important that it be protected as much as possible (e.g., via obfuscation), and only transported over secure channels). Anybody in possession of the key is able to generate a valid secure token!
You can generate an HMAC-SHA256 using the openssl command, as follows:
echo -n "Data to sign" | openssl dgst -sha256 -hmac <hmac-key>
Combine this with the previous hint for Base64URL encoding, and you can generate the JWS signature as follows (note the -binary parameter):
echo -n "<jwt-header>.<jwt-payload>" | openssl dgst -binary -sha256 -hmac <hmac-key> | openssl enc -a -A | tr -d '=' | tr '/+' '_-'
The examples shown above, once concatenated, result in the following token that needs to be signed:
JWT Header+Payload Example
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6ImExYjJjM2Q0ZTUifQ.eyJpc3MiOiJwZHZ5Iiwic3ViIjoiZm9vQGJhci5jb20iLCJpYXQiOjE0Mjk4MDI3MTYsInRkLXJlZyI6dHJ1ZX0
For the following example, we're going to use the "ThisIsASecretValue" string as the HMAC key.
The resulting HS256 (i.e. SHA256 HMAC) signature is:
JWS Signature Example
61e35c7ebed1729bf83fc4eee98d9b46e1aa6141903349478f22bf9c3f1258a0
Encoded (as binary value, not as a string) in Base64URL:YeNcfr7Rcpv4P8Tu6Y2bRuGqYUGQM0lHjyK_nD8SWKA
The final JWT/JWS token and signature, then, is:
Complete JWT Token (Header+Payload+Signature) Example
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6ImExYjJjM2Q0ZTUifQ.eyJpc3MiOiJwZHZ5Iiwic3ViIjoiZm9vQGJhci5jb20iLCJpYXQiOjE0Mjk4MDI3MTYsInRkLXJlZyI6dHJ1ZX0.YeNcfr7Rcpv4P8Tu6Y2bRuGqYUGQM0lHjyK_nD8SWKA