Skip to content

Token design

Martijn van der Ven edited this page May 12, 2018 · 3 revisions

The token is divided in 2 parts:

  1. an identifier consisting of 32 bytes, and
  2. a secret consisting of 72 bytes.

This is comparable to having a username and password.

Identifier

The identifier can contain any number of bytes, this has been arbitrarily set to 32. These are stored as they are so tokens can be retrieved from storage.

As the identifier has to be unique for every token, its length determines how many tokens can be issued in total.

The identifier is possibly susceptible to timing attacks. It may take the database a fraction longer to deny retrieval when an attacker gets the first 6 bytes right, compared to the first 5 bytes. This is why the token also contains a secret.

Secret

The secret contains exactly 72 random bytes, though never null bytes. This maximises the data hashable by the bcrypt algorithm. These are only stored as a hash by the token endpoint, but provided as bytes in the token.

On token verification, the identifier is used to retrieve its specific secret from storage. The bytes that are send as part of the token are then compared to the stored hash in a way safe against timing attacks.

If the token storage is compromised an attacker cannot recreate the exact tokens without cracking every hash separately.

Example

This token may be provided to a client:

1248c41dac3cb18a49dce6baf3849f9231faf6553975021fc0c1578871fdd7cf_7b7aeeb609e6b44307bb1f79c1ad27288f174bb35f86c5d8ea2e393c310a8843996fca7ee2d7532f8ebb5cf2f5d93b60343ddba383fcb216a427d0525debd7b9c0dc795cebb2ff97

It is stored by the endpoint as:

token_id token_hash
1248c41dac3cb18a49dce6baf3849f9231faf6553975021fc0c1578871fdd7cf $2y$10$5LJxeNs/aNWHZvilyM.E7ODUpLl9P3PYDI9e6u4ULofltzY0IYn6S
Clone this wiki locally