springresthttpsession

Avoid REST service to be consumed twice


I have a question about Spring MVC controllers scope and REST services. I have a couple of REST services, which returns a token in the response so I can later recreate the state of the application, but I don't want the users use the same token twice, so I've decided to save an unique identifier inside the token and also in HttpServletRequest, so I can check it when I get the requests (a new identifier is generated in every request).

So, my questions are:

  1. is there any other way to be sure that some user will not use the same token more than once (also considered to save that identifier in DB, but I would have lot of queries to insert, delete, verify, etc.).
  2. is it ok for the controller that receives the requests to be a singleton, or should it be prototype? (considering that the identifier is taken from session and I don't want to mix it between different sessions).

Solution

  • A few words on tokens that are valid only once

    It's not possible to achieve it without keeping the track of the tokens somewhere. This security schema require some trade-offs, deal with it.

    Give the user a token and keep the track of it on server side, just like a white list:

    Also, consider assigning an expiration date to the token and refuse any request that comes to the server with an expired token.

    Regarding your performance concerns: Bear in mind that premature optimization is the root of all evil. You shouldn't optimize until you have a performance problem and you have proven that the performance problem comes from the way you store your tokens. You could start storing the tokens in the database and then consider a cache in memory, for example. But always be careful when fixing a problem that you currently don't have.

    Working with JWT

    If you go for JWT, there are a few Java libraries to issue and validate JWT tokens such as:

    The jti claim should be used to store the token identifier on the token. When validating the token, ensure that it's valid by checking the value of the jti claim against the token identifiers you have on server side.

    For the token identifier you could use UUID. In Java, it's as simple as:

    String uuid = UUID.randomUUID().toString();