29

I am attempting to create a token validation method that returns true if a JWT token is valid based on the signature. I don't think I really need to validate everything in the token but what actually signifies a token is valid after calling ValidateToken()? The existence of a principle? The out referenced token contains certain values? Not sure when to return true from this method.

public bool ValidateToken(string tokenString)
{
    var validationParameters = new TokenValidationParameters()
    {
        ValidIssuer = "My Company",
        ValidAudience = ApplicationId,
        IssuerSigningKey = JsonWebTokenSecretKey
    };

    SecurityToken token = new JwtSecurityToken();
    var tokenHandler = new JwtSecurityTokenHandler();
    var principal = tokenHandler.ValidateToken(tokenString, validationParameters, out token);

    return principal != null;
}
Adam
  • 4,590
  • 10
  • 51
  • 84

1 Answers1

45

I check all of the claims values manually. I've been searching for a definitive answer to your same question but the only thing I have seen is that the ValidateToken function will throw an Exception if something is wrong, so I begin by wrapping the call in a try-catch and return false from the catch.

That's just my "first-pass" at validating the token, though. Afterwards I do a little more heavy lifting to check certain values manually. For example, I make sure that the unique_name value in the claims section actually exists as a user in my database, that the user has not been deactivated, and other proprietary system stuff like that.

    public static bool VerifyToken(string token)
    {
        var validationParameters = new TokenValidationParameters()
        {
            IssuerSigningToken = new BinarySecretSecurityToken(_key),
            ValidAudience = _audience,
            ValidIssuer = _issuer,
            ValidateLifetime = true,
            ValidateAudience = true,
            ValidateIssuer = true,
            ValidateIssuerSigningKey = true
        };

        var tokenHandler = new JwtSecurityTokenHandler();
        SecurityToken validatedToken = null;
        try
        {
            tokenHandler.ValidateToken(token, validationParameters, out validatedToken);
        }
        catch(SecurityTokenException)
        {
            return false; 
        }
        catch(Exception e)
        { 
            log(e.ToString()); //something else happened
            throw;
        }
        //... manual validations return false if anything untoward is discovered
        return validatedToken != null;
    }

The last line, return validatedToken != null, is purely superstition on my part. I've never seen the validatedToken be null.

Eddie Chaplin
  • 576
  • 5
  • 6
  • 11
    Looking at the source code, this indeed seems to be the case: ValidateToken will throw on invalid token. https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/master/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs This is bad design; we shouldn't use exceptions for control flow. But, that's the state of this library today. – Judah Gabriel Himango Nov 27 '16 at 19:48
  • 4
    I had to do something similar in my application to test for token validity, but instead of catching any exception and saying the token is invalid, I would suggest doing something like this instead: `catch(SecurityTokenException ex) { return false; } catch(Exception){ log("something else happened"); throw; }` This way it will only return false if the validate function is actually what threw the error. If something else breaks it won't tell you that your token is invalid. – tkd_aj Mar 24 '17 at 19:14
  • tkd_aj: Thanks for the great suggestion. We should always be as explicit as possible with exceptions. I've updated my answer to include your suggestion. – Eddie Chaplin Mar 27 '17 at 22:55
  • But, how can you get claims? for example, username. – Jeyhun Rahimov May 09 '22 at 10:30