5

I have a question regarding the concept of JWT token type of authentication. So suppose I sign a jwt token after user logged in, the token payload contains the username and userRole. I then return the token to the user and store in user's localStorage.

Now, if i change the userrole in database, i.e. from normalUser to AdminUser, how can I then ensure the payload on user's localStorage also change?

I have an issue when if the user is an admin user, when he signs in, a jwt is stored in his localStorage. Afterwards, I set his role to normal user, he can still access the admin features because his localStorage contains the role of AminUser.

Can someone suggests a correct way to implement authorization so that the token is updated on user end? Thanks.

leo277
  • 433
  • 2
  • 15

2 Answers2

1

What is your trigger for changing the user's authorization? If you're saying that you're opening your database client (Say for example MySQL or PostgreSQL) and manually changing the authorization for the user, then there's no way your server or your client to know of that change (As far as I know at least) and they cannot react to that particular change.

If your trigger was some request sent by the user, say logout or change authorization, then you should respond with the new token for that particular request and store it, easy peasy.

If your trigger wasn't related to your client, and it's somehow something happening on your serverside, then you should have a socket opened between your server and your client, and emit that change from your server to your client.

That way you ensure the client is always up-to-date.

But that's still not enough, because yeah you're keeping the client up to date, but what if he saved the token and replaced it after your update? He/She can still access admin features even though you told them they're just normal users. For that you're gonna need to validate every request done by any of your users, and check if they're allowed to make that request in the first place.

corvus
  • 513
  • 1
  • 3
  • 13
  • ya i think it is gonna be tough, because we don't have a dashboard to assign or change user role, so for now it happens by manually changing database. And because it is a react app, so i'm using state to store the token on client side. – leo277 Nov 18 '19 at 08:59
  • That shouldn't be a problem, because here's the flow you're looking for User is Admin > I change the database and make him a normal user > The user keeps the token (Somehow) > The user sends a request with the admin's token > I check the database > I find out that the user is not an admin as he claims > I reject the request. With that flow you can do what you're looking for even without sockets or triggers. – corvus Nov 18 '19 at 09:02
  • that has a sideeffect though, so if i do the reverse, for example, a normal user > I assign him an admin user > he tries to access admin features, he got denied because his token is for normal user – leo277 Nov 18 '19 at 09:07
  • 1
    unless I dont store the user role in token, and whenever I got a request to api server, i retrieve user object and check the role on server side. – leo277 Nov 18 '19 at 09:08
  • Exactly what I was going to say. – corvus Nov 18 '19 at 09:09
  • but with the above approach only works for server side request. Within react app though, I can't change the token whenever I change db role – leo277 Nov 18 '19 at 09:10
  • Yeah but u just said it, keep the user's token simple, only containing user's information, and retrieve the role from the database all the time, never take it from the client. – corvus Nov 18 '19 at 09:11
  • so for every request I need to authenticate with server, this is quite an expensive approach though. I guess I don't even need the token then. – leo277 Nov 18 '19 at 09:24
  • You'll always need some sort of token, but yeah it is inevitable that you'll need to authenticate every request yourself using your own server or some service like AWS cognito. – corvus Nov 18 '19 at 09:26
1

You cannot really trust clients. You should find a way to invalidate your jwt tokens. Your client should get a new token when you reject them. You can rotate your tokens using refresh key.

In order to do that:

  • Keep your token lifetimes short

Or:

  • Store blacklisted tokens in the database and reject the invalidated tokens.
Ozan Bulut
  • 735
  • 4
  • 14
  • I'm storing in localStorage, so perhaps I should store token in session and make the life time short. So that they will be forced relogin more frequently. I think that is the best way for now because we don't have enough time to implement more complicated logic. – leo277 Nov 18 '19 at 09:01
  • Keep in mind that it's not really secure way. You should keep expiration data inside your jwt token. Your backend should control authentication and authorization. – Ozan Bulut Nov 18 '19 at 09:12
  • can you set expiration for jwt token in localStorage? – leo277 Nov 18 '19 at 09:29