I have been playing around with Asp.Net Core and JWT to learn about JWT. One of my processes is always to make things 'unwork' by removing and altering information. While I did this, I noticed that my project would authorise a token as long time it just contained the following payload (the payload had been genereted by the api and I removed everything, but the parts below):
{
"exp": 1633534580,
"iss": "http://localhost:59921",
"aud": "http://localhost:4200"
}
This would seem like a security issue, since 'iss' and 'aud' would stay constant over time and only the 'exp' would have to be guesses correctly, which would be hard, to get a valid token. Thus, I would like to know how Identity handles a JWT to determine if it is valid and what I, as a developer, could do or implement to increase the security of using JWTs to allow people access to my api's endpoints?
The code that generetes the token is this:
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
var user = await userManager.FindByNameAsync(model.Username);
if (user != null && await userManager.CheckPasswordAsync(user, model.Password))
{
var userRoles = await userManager.GetRolesAsync(user);
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
foreach (var userRole in userRoles)
{
authClaims.Add(new Claim(ClaimTypes.Role, userRole));
}
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Secret"]));
var token = new JwtSecurityToken(
issuer: _configuration["JWT:ValidIssuer"],
audience: _configuration["JWT:ValidAudience"],
expires: DateTime.Now.AddHours(3),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
});
}
return Unauthorized();
}
My startup file contains this, regarding authenthication.
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = Configuration["JWT:ValidAudience"],
ValidIssuer = Configuration["JWT:ValidIssuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Secret"]))
};
});
The code is based upon this article: https://www.c-sharpcorner.com/article/authentication-and-authorization-in-asp-net-5-with-jwt-and-swagger/
--- Edit --- I guess that for someone to generate a token, they would also need to know the secret key in the signature, which does add some extra security.
CodePudding user response:
JWTs are self-contained, by-value tokens and it is very hard to revoke them, once issued and delivered to the recipient. Because of that, you should use as short expiration time for your tokens as possible - minutes or hours at maximum. You should avoid giving your tokens expiration times in days or months.
Remember that the exp claim, containing the expiration time, is not the only time-based claim that can be used for verification. The nbf claim contains a “not-before” time. The token should be rejected if the current time is before the time in the nbf claim. Another time-based claim is iat - issued at. You can use this claim to reject tokens which you deem too old to be used with your resource server.
When working with time-based claims remember that server times can differ slightly between different machines. You should consider allowing a clock skew when checking the time-based values. This should be values of a few seconds, and we don’t recommend using more than 30 seconds for this purpose, as this would rather indicate problems with the server, rather than a common clock skew.
Regarding security, jWT security largely depends on how the token is implemented and used. Just because the JWT contains a cryptographic signature, it does not automatically mean that it is secure, or you should blindly trust the token.
You can pay attention to the security standards and security levels of cryptography:
JSON Web Token Best Current Practices and RFC 7518 JSON Web Algorithms (JWA)