Reputation: 1522
I successfully implemented JWT as a authentication filter in my web application. When user's login
is successful, I am creating a new JWT
and assigning userName
in the sub
field of JWT
.
In the subsequent request's I am using userName
in the JWT
sub
field to identify the user. But what if the user changes his userName
in the update section of the application. Is there way, I can update the value of sub
field in JWT
?
What I am thinking!
I am thinking of getting the existing JWT
in the RestController
and after updating the userName
, I will update the JWT
with new userName
and again send back to the client. Is this fine or is there a better approach?
Upvotes: 1
Views: 1595
Reputation: 659
If you allow your users to change their usernames, they should also have an immutable user id that can be used to identify any data or activity associated with a given user. Otherwise, any time a user changes his or her name, you will either lose the ability to audit the user's past actions or you will have to update all references to that username in the database. What's worse is if there are references to an old username in the database and another user takes that username -- now you have data from one user now being associated with another due to incorrect handling of user identification.
Now with that said, the sub claim should contain this immutable user id. You can create a separate claim for the mutable username. When a username is changed, you now only need to change a single field in the database (assuming that only the users table references this mutable username). You could then use the refresh token retrieve a new token that would contain the latest username that could then be used by your API as needed.
Using this approach, you should be careful to only use the username claim for display purposes, not for identifying the logged in user due to the fact that it is mutable. The sub claim containing the user id would serve the purpose of identifying a user.
It is also important to note that this solution requires no special logic for "updating the sub claim." You would be using the same logic that you're already using to generate a token for a supplied refresh token.
Upvotes: 1
Reputation: 1522
I think I should refresh the token after update is done and send back the refreshed token back to client.
@RequestMapping( value = "/account", method = RequestMethod.POST )
public ResponseEntity<?> updateAccount( @RequestBody UserDetailsBean userDetailsBean, HttpServletRequest request,
HttpServletResponse response )
{
try
{
UserAccessDetails accessDetails = getLoggedInUser();
UserDetailsBean updatedUserBean = userService.updateAccount(userDetailsBean, accessDetails);
// send updated jwt incase of mobile number update by user
response.addHeader(SecurityConstants.HEADER_STRING,
SecurityConstants.TOKEN_PREFIX + refreshJWT(updatedUserBean.getMobileNumber()));
return buildResponse(updatedUserBean);
}
catch( DataException e )
{
return buildError(e);
}
}
private String refreshJWT( String subject )
{
return Jwts.builder().setSubject((subject))
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SecurityConstants.SECRET).compact();
}
This is working. If anyone has a cleaner and industry standard approach please specify.
Upvotes: 1