I have to admit, I've just created a REST API using the approach like the one described above:
We provide a username and secret for each client, which is allowed to access our REST service.
The client has to generate a new JWT for each REST call and has to add the token to the request header.
Why did I choose this approach and what are the advantages and disadvantages in my eyes?
First of all, we only have a single server providing the REST service. There is no need for us to use a different authentication server, which seems to be the most common use for JWT.
In a normal JWT scenario, the client provides credentials (username and password) to the server and receives a server generated JWT containing API access information as payload. This JWT is then used for each REST call over and over again. Of course, the password is to be kept secret by the client.
My approach works as follows:
The client creates a JWT with the following payload:
- username
- HTTP Method and name of REST method to call
- timestamp
- unique nonce
The JWT is signed using the client's secret.
The server identifies the user via the username from he payload and validates the signiture using the user's secret stored on the server.
In my eyes, this approach has the following advantages:
- The secret (like the password in the normal approach) has to be kept secret by the client too, BUT is never transferred between client and server.
Additional security against man in the middle and replay attacks:
- the token is only valid for one REST call because of the unique nonce.
- the token can only be used for the REST service the client wanted to call, because HTTP method and REST service name is included in the payload.
- The JWT is only valid for a limited time (1 Minute in our case) because of the timestamp.
- The user can be identified by the server via the username, the server than manages access rights by retrieving user configuration from an internal database. If you have many user related properties and settings, this has some benefits over putting all those information into the static JWT as you would in the normal approach, which might result in a quite large token and which might even reveal some credential information. For example, if some REST calls are charged to the client and you really don't look up user information on the server side, pricing information might be included into the JWT.
Disadvantages might be:
- JWT must be created on client side for each call, which might consume some processing power and adds overhead to the implementation.
- The server must acquire user information from the database (or some kind of cache) for each call.
- The pre shared secret must be kept secret on client and server side. The server must know the secret and can not store only a hash like you can do with a password.
So my use of JWT does not focus on using an single authentication server or a stateless serverside, but on hardening against MITM and replay attacks.
Every opinion on this approach is welcome.