Reputation: 700
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 A
s 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 id
claim as part of payload that is unique and
cannot be easily guessed? Due to this B
cannot derive the
correct set of claims to create the exact A
s 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 secret
key 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.
Upvotes: 1
Views: 552
Reputation: 1684
Option #2 - If using symmetric keys never, ever disclose them to the client if the client is unsecured in any way, particularly if the client is a web application. It's a good idea to just not ever give out the symmetric keys. JWTs should be manufactured on a/the server i.e pre-signed with the symmetric key and then given to the client. The client can ask for a JWT by means of a secured API via some form of authentication, or you can create the JWT and dole out to a client by other means.
We do both. Domain users that are already authenticated can request an expiring JWT via an API call. User's outside of the domain are delivered a JWT specifically for them by an approved adminstrator on the domain that can access the API call. At no time is the symmetric key(s) exposed.
This process starts to duplicate some aspects of OAuth, so you might want to investigate OAuth servers/vendors, which is where we are going.
Upvotes: 1