This is my token decoder. When I try to decode it, my principal ends up being null thus leading to this error:
'IDX10208: Unable to validate audience. validationParameters.ValidAudience is null or whitespace and validationParameters.ValidAudiences is null.'
When I decode my token to check
"nbf": 1539167980, "exp": 1539168580, "iat": 1539167980, "iss": "http://localhost:55260", "aud": "http://localhost:55260"
This is the host that my token generator runs on as well. Why is the principal causing issues?
public class DecodeToken
{
private IConfiguration configuration;
public DecodeToken(IConfiguration configuration)
{
this.configuration = configuration;
}
public AuthenticationDto Decode(String Input)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JwtAuthentication:SecurityKey"]));
var handler = new JwtSecurityTokenHandler();
var tokenSecure = handler.ReadToken(Input) as SecurityToken;
var validations = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = false
};
SecurityToken securityToken;
var principal = handler.ValidateToken(Input, validations, out securityToken);
var jwtSecurityToken = securityToken as JwtSecurityToken;
if (jwtSecurityToken == null || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
{
throw new SecurityTokenException("Invalid Token");
}
AuthenticationDto authenticationDto = new AuthenticationDto
{
Email = principal.Claims.Where(c => c.Type == "Email").Select(c => c.Value).SingleOrDefault(),
UserName = principal.Claims.Where(c => c.Type == "UserName").Select(c => c.Value).SingleOrDefault(),
FirstName = principal.Claims.Where(c => c.Type == "FirstName").Select(c => c.Value).SingleOrDefault(),
LastName = principal.Claims.Where(c => c.Type == "LastName").Select(c => c.Value).SingleOrDefault(),
PhoneNumber = principal.Claims.Where(c => c.Type == "PhoneNumber").Select(c => c.Value).SingleOrDefault(),
Id = principal.Claims.Where(c => c.Type == "Id").Select(c => c.Value).SingleOrDefault(),
ExpiryDateTime = principal.Claims.Where(c => c.Type == "exp").Select(c => c.Value).SingleOrDefault(),
Roles = principal.Claims.Where(c => c.Type == "Roles").Select(c => c.Value).ToList(),
};
return authenticationDto;
}
}
This is what my Startup.cs looks like:
services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = "Jwt";
options.DefaultChallengeScheme = "Jwt";
})
.AddJwtBearer("Jwt", options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtAuthentication:SecurityKey"])),
ValidateIssuer = true,
ValidIssuer = Configuration["JwtAuthentication:Issuer"],
ValidateAudience = true,
ValidAudience = Configuration["JwtAuthentication:Audience"],
ValidateLifetime = true, //validate the expiration and not before values in the token
ClockSkew = TimeSpan.Zero //5 minute tolerance for the expiration date
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
}
};
});
Have I configured something wrong?
Your error appears to make perfect sense. In ConfigureServices, you're setting up the TokenValidationParameters so that it validates your issuer/audience and you're providing values for ValidIssuer and ValidAudience, but you're not doing the same in your Decode function, where you're only setting ValidateIssuer and ValidateAudience without setting the values that you expect. You need to configure these on your validations variable in Decode, like this:
var validations = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = false,
// Add these...
ValidIssuer = configuration["JwtAuthentication:Issuer"],
ValidAudience = configuration["JwtAuthentication:Audience"]
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With