Naanavanalla
Naanavanalla

Reputation: 1522

Dynamically changing JWT subject field

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

Answers (2)

dsep
dsep

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

Naanavanalla
Naanavanalla

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

Related Questions