Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement 'jti' parameter for jwt to prevent replay attacks #265

Closed
F21 opened this issue Nov 29, 2013 · 4 comments
Closed

Implement 'jti' parameter for jwt to prevent replay attacks #265

F21 opened this issue Nov 29, 2013 · 4 comments

Comments

@F21
Copy link
Contributor

F21 commented Nov 29, 2013

The 'jti' parameter in a JWT is a nonce to prevent replay attacks. This is currently optional in the spec and is not currently implemented in the library.

We should add support for checking the jti to see if it has been used. If so, the request should be denied.

@bshaffer
Copy link
Owner

Sounds reasonable. Is this something you want to submit a PR for?

@F21
Copy link
Contributor Author

F21 commented Nov 30, 2013

@bshaffer I would love to submit a PR, but would like some input on how we should expire the jti. The spec says that the jti cannot be reused for the duration of the exp parameter (once it has been used).

However, the question is how unique the jtis have to be. For instance, we can have a simple implementation where we have a list of jtis with their associated exps. Any jti that is on the list and not expired and reused will be denied.

However, we can also make it a bit "smarter" by linking the jti to the iss, sub, and aud parameters. So, for a jti to be denied, all of those parameters must match and the token should not be expired.

Once we have decided how to deal with that, implementation should be quite trivial.

Cheers 😄

@F21
Copy link
Contributor Author

F21 commented Dec 14, 2013

@bshaffer Let's reopen this for some further discussion as I think I would like to push an update to this.

Unfortunately, the spec doesn't give any guidance on how the JTIs should be generated:

"jti" (JWT ID) Claim

The jti (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object. The jti claim can be used to prevent the JWT from being replayed. The jti value is a case-sensitive string. Use of this claim is OPTIONAL. 

So, the following approaches for generating a nonce may be considered valid:

  • Have a counter that increments the nonce for each new jwt generated.
  • Use the current timestamp as the nonce.
  • Use the md5 hash of the jwt.

The above would cause collisions if 2 clients use the same scheme for generating the jtis.
Since the jtis are generated by the client, there is no way we can control their implementation.

I would like to modify the storage implementation to the following:

public function getJti($client_id, $jti, $jwt)
public function setJti($client_id, $jti, $jwt);

Instead of passing the jwt parameters to the storage implementations, we are passing the client_id jti and the decoded jwt.

This means that we could hopefully steer implementations to do the following:

  • Match only jtis with client_ids. This prevents clients using simplistic nonce generating routines to affect other clients.
  • Provide the decoded jwt, so that if required, the implementer can produce some sort of hash of the jwt to compare against if he feels he needs each nonce to be unique on a JWT basis.

I recommend something like this for generating the jti, but since the spec does not give any guidance, pretty much any generating method is valid:

$random_number = ... //generate using openssl_random_pseudo_bytes
$jti = hash('sha256', serialize($jwt) . $random_number);

In conclusion:

  • Encourage storage implementers to check for nonce collisions on a client_id basis. One client's nonce should not affect another's. This is good practice in my opinion.
  • If required, the jwt is provided if the implementer wants to check for jtis on a JWT basis.

Would love to hear your feedback on this! 😄

@Sicaine
Copy link

Sicaine commented Jan 6, 2017

@F21 i'm just answering because i found it through google and someone else might find it:
I would only use uuid (in version 4). It reduces the risk of collisions to a level where i can trust it enough to generate unique ids.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants