C
C#3w ago
Cydo

✅ JTI not being pulled from payload when I am trying to validate token

I create an access token store all the claims i want on it and get an access token and this is what the payload looks like when its decoded Creating Access Token
private string CreateAccessToken(ApplicationUser user, string sessionId)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_jwtSecret);

var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, user.UserName.ToString()),
new Claim(JwtRegisteredClaimNames.Jti, sessionId),
new Claim(JwtRegisteredClaimNames.Sub, user.Id),
}),
Expires = DateTime.UtcNow.AddMinutes(30),
SigningCredentials = new(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
Issuer = "https://localhost:7059",
Audience = "http://localhost:5173"
};

var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenStr = tokenHandler.WriteToken(token);

return tokenStr;
}
private string CreateAccessToken(ApplicationUser user, string sessionId)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_jwtSecret);

var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, user.UserName.ToString()),
new Claim(JwtRegisteredClaimNames.Jti, sessionId),
new Claim(JwtRegisteredClaimNames.Sub, user.Id),
}),
Expires = DateTime.UtcNow.AddMinutes(30),
SigningCredentials = new(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
Issuer = "https://localhost:7059",
Audience = "http://localhost:5173"
};

var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenStr = tokenHandler.WriteToken(token);

return tokenStr;
}
{
"unique_name": "Test",
"jti": "SESS73ab5ea8-2c67-42a9-ba6e-96241dad5b0a",
"sub": "bababf79-a2bc-49b3-9690-206acd714bd0",
"nbf": 1732389177,
"exp": 1732390948,
"iat": 1732389177,
"iss": "https://localhost:7059",
"aud": "http://localhost:5173"
}
{
"unique_name": "Test",
"jti": "SESS73ab5ea8-2c67-42a9-ba6e-96241dad5b0a",
"sub": "bababf79-a2bc-49b3-9690-206acd714bd0",
"nbf": 1732389177,
"exp": 1732390948,
"iat": 1732389177,
"iss": "https://localhost:7059",
"aud": "http://localhost:5173"
}
3 Replies
Cydo
CydoOP3w ago
Now when I go to verify that access token for some reason half the claims just dissapear, and i have no idea why
private bool CheckIfAccessTokenIsValid(string accessToken, string expectedUserId, string expectedSessionId)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var jwt = tokenHandler.ReadJwtToken(accessToken);
var sessionId = jwt.Claims.FirstOrDefault(claim => claim.Type == JwtRegisteredClaimNames.Jti).Value;
var userId = jwt.Claims.FirstOrDefault(claim => claim.Type == JwtRegisteredClaimNames.Sub).Value;

return userId == expectedUserId && sessionId == expectedSessionId;
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
return false;
}
}
private bool CheckIfAccessTokenIsValid(string accessToken, string expectedUserId, string expectedSessionId)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var jwt = tokenHandler.ReadJwtToken(accessToken);
var sessionId = jwt.Claims.FirstOrDefault(claim => claim.Type == JwtRegisteredClaimNames.Jti).Value;
var userId = jwt.Claims.FirstOrDefault(claim => claim.Type == JwtRegisteredClaimNames.Sub).Value;

return userId == expectedUserId && sessionId == expectedSessionId;
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
return false;
}
}
The JIT claim is never present but its present on the incoming access token. and my debugger says only these claims are present
{
"unique_name": "Test",
"sub": "bababf79-a2bc-49b3-9690-206acd714bd0",
"exp": 1732390948,
"iat": 1732389177,
"iss": "https://localhost:7059",
}
{
"unique_name": "Test",
"sub": "bababf79-a2bc-49b3-9690-206acd714bd0",
"exp": 1732390948,
"iat": 1732389177,
"iss": "https://localhost:7059",
}
Figured it out
SteveTheMadLad
What was it? I read your post and it got me curious, as I recently did something similar and had no issue.
Cydo
CydoOP3w ago
Sorry never got a notification for this, The issue was a variety of things tbh but the way I ended up fixing it was using a different package for jwt's So instead of using JwtSecurityTokenHandler, i used JsonWebTokenHandler which is apparently the newer and prefered way to do Jwt's and then changes a few other things you'd have to do since the methods from that handler are async. So the two methods completely changed to work now look like this
private string CreateAccessToken(ApplicationUser user, string sessionId)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSecret));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);


var tokenDescriptor = new SecurityTokenDescriptor()
{
Subject = new ClaimsIdentity(new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.Id),
new Claim(JwtRegisteredClaimNames.Jti, sessionId),
}
),
Expires = DateTime.UtcNow.AddMinutes(30),
SigningCredentials = credentials,
Audience = _jwtAudience,
Issuer = _jwtIssuer
};

var tokenHandler = new JsonWebTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return token;
}
private string CreateAccessToken(ApplicationUser user, string sessionId)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSecret));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);


var tokenDescriptor = new SecurityTokenDescriptor()
{
Subject = new ClaimsIdentity(new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.Id),
new Claim(JwtRegisteredClaimNames.Jti, sessionId),
}
),
Expires = DateTime.UtcNow.AddMinutes(30),
SigningCredentials = credentials,
Audience = _jwtAudience,
Issuer = _jwtIssuer
};

var tokenHandler = new JsonWebTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return token;
}
private async Task<bool> CheckIfAccessTokenIsValid(string accessToken, string expectedUserId,
string expectedSessionId)
{
try
{
var tokenHandler = new JsonWebTokenHandler();
var key = Encoding.ASCII.GetBytes(_jwtSecret);

var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ClockSkew = TimeSpan.Zero
};

var tokenValidationResult = await tokenHandler.ValidateTokenAsync(accessToken, tokenValidationParameters);

var userId = tokenValidationResult.Claims.FirstOrDefault(c => c.Key == "sub").Value?.ToString();
var sessionId = tokenValidationResult.Claims.FirstOrDefault(c => c.Key == "jti").Value?.ToString();

return userId == expectedUserId && sessionId == expectedSessionId;
}
catch
{
return false;
}
}
private async Task<bool> CheckIfAccessTokenIsValid(string accessToken, string expectedUserId,
string expectedSessionId)
{
try
{
var tokenHandler = new JsonWebTokenHandler();
var key = Encoding.ASCII.GetBytes(_jwtSecret);

var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ClockSkew = TimeSpan.Zero
};

var tokenValidationResult = await tokenHandler.ValidateTokenAsync(accessToken, tokenValidationParameters);

var userId = tokenValidationResult.Claims.FirstOrDefault(c => c.Key == "sub").Value?.ToString();
var sessionId = tokenValidationResult.Claims.FirstOrDefault(c => c.Key == "jti").Value?.ToString();

return userId == expectedUserId && sessionId == expectedSessionId;
}
catch
{
return false;
}
}
And these are the packages
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.11" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.2.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.11" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.2.1" />
Want results from more Discord servers?
Add your server