The question more focuses on the correct usage of JWT, after clarifying few thoughts.
Let's talk about only encoded (not encrypted) JWTs, and let's consider only HMAC which uses a symmetric secret key, let's call this p@$$w0rd which will be used to sign the JWT.
We know that JWTs should not contain sensitive information as they do not hide any data as payload is only Base64 encoded, they are only supposed to verify through the signature that information is coming from correct client.
In our case we are sending role for the purpose of showing/hiding certain elements from our Web application.
As in a user with admin role will see links to create/modify/delete users, etc as an example.
Scenario
A -> an admin user, requests JWT from Server (issuer) upon Login
Server -> Issues JWT with claims of userID, userName, role and with an expiration date.
A -> supposed to send this JWT token upon all further API requests to the server and server will use this token to authenticate.
B -> is a non-admin user and follows same procedure.
B knows that A is an admin user and knows it's userID and userName as well. This is very likely possible, nowhere there is sensitive information.
JWT only has claims Base64 encoded and if the client knows the secret p@$$w0rd as well, the token can be easily generated by the client. As we know the verifier server only re-hashes the encoded JWT (coming from client) to match the one it sent upon login using the secret.
Through https we can be sure that 3rd party or man in the middle has no way to know this secret or any other information, so let's leave that aside.
#1
B being a malicious user modifies it's own token and changes the role to that of admin and makes an API call only permissible to admin users.
Server can easily invalidate this token as the re-hashing will fail because the original token issued to B was modified and when we modify the token the signature also changes as it's made up of payload as well.
#2
B being a malicious user creates a token to match that of A with all of As details and makes an API request only permissible to admin users.
The server will successfully verify that token and come to know that it's A.
How to prevent this?
Should we use an
idclaim as part of payload that is unique and cannot be easily guessed? Due to thisBcannot derive the correct set of claims to create the exactAs token. Although this approach is a bit more involved in storing this extra ID for every user and authenticating at server.Should we never disclose the
secretkey used to sign the JWT, so
the client can ever create the token?
We know that JWTs are certainly a better way to authenticate as compared to Basic Authorization which sends the user's Base64 encoded password as well in every API request which has a much larger attack window.