The original threat model for this should be: attacker gets a read-only copy of the database, we should not allow them to make authenticated requests. In other words, BOTH the client AND the backend database record should be prevented from recovering or forging valid tokens.
The properties I think we should aim for:
- Contain data secret from the server, ideally in a way that can be used without ever being revealed back to the server
- Contain some authenticated or verifiable plaintext claims (like token type, application id, etc)
- Rotation and revocation should be possible without changing the claim itself
- Backwards compatible with verbatim tokens
- Not too long for webhook forms with length limits
- Not too rigidly bound to the entity ontology (i.e. a token doesn't necessarily need to have an associated user) for future features like sharing messages
A new token could look something like this:
- A literal G (or gtfy), to distinguish it with old tokens.
- Underscore.
- A sequence of claims separared by underscore, a single letter denoting the next claim type, like "U1" means user ID 1, "A2" means application ID 2, "P3" means accessing resources for plugin 3. This is already similar to the property based authorization system in the auth package.
- An underscore.
- The "key" encoded in the token, randomly generated by the server at creation time. The server only records response of HMAC(key=key,salt=claims) and never commits the key to the database, so someone with read-only access to the database still have an HMAC preimage problem to solve to find a valid "key". (HKDF might be better in order to protect against confused deputy scenarios and gives us more degrees of freedom on binding more necessary context without canonicalization headaches, but we can decide that as we write the PR)
- Optional/for future: A period (.) then a counter , IIRC way back in the original discussion I put forward some reservations on the practical security of merely hashing a token and yet demand the client to send the "answer" to you in every request. This part of the token being present causes the database to update the max counter recorded in the system for each token, and the "key" part being double hashed with a further message containing the counter instead of the key itself. We can detail this up in another discussion.
- For future proofing we might want to generate "keys" that are in addition to being unpredictable, but also valid private keys in a public key crypto system (Curve25519, etc)
Currently we will only issue tokens mapping back to the current system, like "gtfy_U1_A2_0123456789abc"
Footnote: the HMAC output can be simply stored by reusing the token field, we just need to make sure they don't start with "ACP" so they can't be confused with legacy verbatim tokens
References:
#325
#964 (comment)
An old PR that is finally unblocked with #964: #707
@jmattheis
The original threat model for this should be: attacker gets a read-only copy of the database, we should not allow them to make authenticated requests. In other words, BOTH the client AND the backend database record should be prevented from recovering or forging valid tokens.
The properties I think we should aim for:
A new token could look something like this:
Currently we will only issue tokens mapping back to the current system, like "gtfy_U1_A2_0123456789abc"
Footnote: the HMAC output can be simply stored by reusing the token field, we just need to make sure they don't start with "ACP" so they can't be confused with legacy verbatim tokens
References:
#325
#964 (comment)
An old PR that is finally unblocked with #964: #707
@jmattheis