Published using Google Docs
JSON Tokens
Updated automatically every 5 minutes

JSON Tokens

This document specifies how to sign arbitrary data structures in a Web-friendly way, and how to verify signatures on them. This is similar to, and inspired by, Magic Signatures, but a little bit different, as the result is a token that can be included in URLs (as opposed to the JSON or XML format output by Magic Signatures).

JSON Tokens are created by issuers, and consumed by verifiers.

Server Descriptors

A server descriptor is a https or http URL. This URL resolves to a document that describes the server (such as keys used to sign requests or tokens, location of certain endpoints, etc.). Details of the document are described below in the Discovery section.


A verifier must be able to determine the server descriptor of the issuer from the “issuer” field in the token payload (see below). For example, verifiers could specify that issuers put their service descriptor directly in the “issuer” field. Alternatively, verifiers could require issuers to pre-register with the verifier, create a “client id” for the issuer, and maintain a mapping from client ids to server descriptors of issuers. In this latter case, issuers would include their client id into the “issuer” field of the token payload.

Token Structure

JSON tokens have the following structure (|| means concatenation):

payload || “.” || signature

payload is an unpadded websafe-base64-encoded JSON that includes at least the following fields:

Name

Value Type

Value Semantics

issuer

string

A string that allows the verifier to determine the server descriptor of the issuer. This could be the service descriptor itself, or some form of client id, which the verifier can map to a server descriptor (see above).

key_id

string

Identifies the key uses by the issuer.

algorithm

string

Identifies the signing algorithm used.

not_before

integer

When does this token becomes valid (seconds since midnight 1/1/1970 zulu).

not_after

integer

When does this token expire (seconds since midnight 1/1/1970 zulu).

audience

string

The audience for this token. The precise semantics of this field, and how it is validated, depends on the application.

Issuers can include more fields (of arbitrary types) in the payload.

signature is a websafe-base64-encoded string of the signature bits. The signature is over the actual octets of the payload.

Validation of JSON Tokens

When receiving a JSON Token, a client can validate the token, provided it has access to a signature verification key (discussed in further detail below). It needs to perform the following steps:

  1. extract the key identifier from the token, obtain verification key for the issuer and key identifier (more details below).
  2. using verification key, verify signature on payload (using the signature algorithm identified).
  3. verify that the current time is not before the not_before timestamp in the payload, and that the current time is not after the expiration time of the token (defined as not_before + token_lifetime). The verifier SHOULD be lenient and anticipate some clock skew on the issuer’s side.
  4. verify the audience field in an application-dependent manner.

Obtaining Verification Keys

We define two signature algorithms in this document: HMAC-SHA256 and RSA-SHA256. HMAC keys are obtained differently from RSA keys. RSA-SHA256 must be used with the RSASSA-PSS algorithm (in Java the corresponding RSA-SHA256 algorithm name is “SHA256withRSAandMGF1”).

Obtaining RSA Verification Keys

To obtain an RSA verification key, the client accesses the Server Descriptor of the issuer (perhaps after mapping the issuer string obtained from the token payload to the Server Descriptor), and parses the returned document. The returned document may include one or more public keys, labeled with key identifiers (details below in the Discovery section). The key that matches the key_id from the token’s payload shall be used to verify the token.

Obtaining HMAC Verification Keys

To obtain an HMAC verification key, the verifier has to exchange, in an out-of-band fashion, shared keys with the issuer. Each key must be labeled with an identifier, unless there is only one shared key at any given point in time, in which case no label is necessary, and the key_id parameter in the payload will be ignored by the client.

Discovery

Server Descriptors resolve directly to “server information” documents that contain data about the servers. For now, we only describe the “verification_keys” data type, but it’s easy to imagine how other information can be embedded in these documents.

Server information documents are a simple JSON dictionary - for now, only the “verification_keys” dictionary key is defined. The value of the verification_keys key is a dictionary that maps from key identifiers to public keys. A public key is either of the form “RSA.<modulus>.<exponent>” as explained in the Magic Signatures spec, or of the form “X509.<certificate>”, in which the certificate is the websafe-base64-encoded DER representation of an X.509 certificate (using the web-safe base64 alphabet and no chunks).

Example

Below is an example server info document:

{

  "verification_keys":  {"key1":"RSA.ALqcwR..."}

}

Caching

Server info documents can be cached by verifiers for as long as the HTTP response headers indicate. If the verifier encounters a JSON Token with a key id that is not in the cached server document, it should re-resolve the issuer’s Server Descriptor. If the verifier encounters a JSON Token with a key id from an expired server info document, the verifier must re-resolve the issuer’s Server Descriptor and validate the JSON Token only if a key with that key id is still present in the server descriptor document.