JWT is issuing the same token

前端 未结 1 1047
后悔当初
后悔当初 2020-12-29 15:03

I am making a rest API with Jersey. I am using java-jwt(https://github.com/auth0/java-jwt) for my token generation work. Please check the below cod

相关标签:
1条回答
  • 2020-12-29 15:31

    What authentication scheme based on tokens is about

    In an authentication scheme based on tokens, the token becomes a credential of the user. Hard credentials such as username and password are exchanged for a token that must be sent in each request then the server can perform authentication/authorization. Tokens can be valid for a short amount of time, can be revoked, can carry scope details (what can be requested with the token), etc.

    With a token, you must be able to identify the user who is targeting your API. Hence it makes no sense having a single token for all authenticated users.

    Addressing your issue

    Once you are using JWT, you could have a claim with the username. Also consider adding an expiration date for you token (exp claim). You don't want your​ token to be valid forever, do you?

    With java-jwt, use the following:

    try {
    
        Algorithm algorithm = Algorithm.HMAC256("secret");
        Date expirationDate = Date.from(ZonedDateTime.now().plusMinutes(60).toInstant());
        String token = JWT.create()
                          .withExpiresAt(expirationDate)
                          .withClaim("username", username)
                          .sign(algorithm);
    
    } catch (UnsupportedEncodingException e){
        // UTF-8 encoding not supported
    } catch (JWTCreationException e){
        // Invalid signing configuration / Couldn't convert claims
    }
    

    When verifying the token, you'll be able to get the username claim and know who you issued the token for:

    try {
    
        Algorithm algorithm = Algorithm.HMAC256("secret");
        JWTVerifier verifier = JWT.require(algorithm).build();
        DecodedJWT jwt = verifier.verify(token);
    
        Claim usernameClaim = jwt.getClaim("username");
        String username = usernameClaim.asString();
    
    } catch (UnsupportedEncodingException e){
        // UTF-8 encoding not supported
    } catch (JWTVerificationException e){
        // Invalid signature/claims
    }
    

    Handling token refreshment with JWT

    Accept only valid (an non-expired) tokens for refreshment. It's responsability of the client to refresh the tokens before the expiration date indicated in the exp claim.

    To avoid a token from being refreshed indefinitely, you could keep the track of the token refreshment by adding two claims to your token (the claim names are up to you):

    • refreshLimit: Indicates how many times the token can be refreshed.
    • refreshCount: Indicates how many times the token has been refreshed.

    So only refresh the token if the following conditions are true:

    • The token is not expired (exp >= now).
    • The number of times that the token has been refreshed is less than the number of times that the token can be refreshed (refreshCount < refreshLimit).

    And when refreshing the token:

    • Update the expiration date (exp = now + some-amount-of-time).
    • Increment the number of times that the token has been refreshed (refreshCount++).

    Once the token is signed and the signature is verified on server side, the content of the token cannot be tampered by the client.

    Alternatively to keeping​ the track of the number of refreshments, you could have a claim that indicates the absolute expiration date. Before that date, any number of refreshments are acceptable.

    Another approach involves issuing a separate long-lived refresh token that is used to issue short-lived JWT tokens.

    The best approach depends on your requirements.

    Handling token revocation with JWT

    If you want to revoke tokens, you must keep the track of them. You don't need to store the whole token on server side, store only the token identifier (that must be unique) and some metadata if you need. For the token identifier you could use UUID.

    The jti claim should be used to store the token identifier on the token itself. When validating the token, ensure that it has not been revoked by checking the value of the jti claim against the token identifiers you have on server side.

    For security purposes, revoke all the tokens for a user when they change their password.


    For more details on token-based authentication in JAX-RS, refer to this answer.

    0 讨论(0)
提交回复
热议问题