I am creating an ASP.NET Core Web API. In this, I am using JWT token for authentication. I have created a demo SQL database for testing and I am testing my APIs using Fiddler. My ConfigureServices
method of Startup
class looks like this:
public void ConfigureServices(IServiceCollection services)
{
var authPol = new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes(
new string[] { JwtBearerDefaults.AuthenticationScheme })
.RequireAuthenticatedUser()
.Build();
services.AddControllers(
config =>
{
config.Filters.Add(new AuthorizeFilter(authPol));
}).AddXmlSerializerFormatters()
.AddXmlDataContractSerializerFormatters();
services.AddDbContext<BikeStoresContext>();
// JWT Token
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("this-is-my-jwt-security-key"));
var tokenValidationParameters = new TokenValidationParameters()
{
IssuerSigningKey = signingKey,
ValidateIssuer = false,
ValidateAudience = true,
ClockSkew = TimeSpan.Zero
};
services.AddAuthentication(x => x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwt =>
{
jwt.TokenValidationParameters = tokenValidationParameters;
});
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<BikeStoresContext>()
.AddDefaultTokenProviders();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "BikeStoreAPI", Version = "v1" });
});
}
This is my JWT token generation code from Accounts controller's login action method:
var user = await userManager.FindByEmailAsync(model.UserEmail);
var roles = await userManager.GetRolesAsync(user);
IdentityOptions identityOptions = new IdentityOptions();
var claims = new Claim[]
{
new Claim("Lid", "123456789"),
new Claim(identityOptions.ClaimsIdentity.UserIdClaimType, user.Id),
new Claim(identityOptions.ClaimsIdentity.UserNameClaimType, user.UserName),
new Claim(identityOptions.ClaimsIdentity.RoleClaimType, roles[0]),
new Claim(identityOptions.ClaimsIdentity.EmailClaimType, user.Email)
};
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("this-is-my-jwt-security-key"));
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
var jwt = new JwtSecurityToken(claims: claims,
signingCredentials: signingCredentials,
expires: DateTime.Now.AddMinutes(30));
return Ok(new
{
userName = model.UserEmail,
role = roles[0],
token = new JwtSecurityTokenHandler().WriteToken(jwt)
});
JWT token is generated, but when I used the JWT token to access other APIs, I am getting this error.
WWW-Authenticate: Bearer error="invalid_token", error_description="The audience 'empty' is invalid"
I don't know where I made mistake in this code. Is there any change required?
Fiddler Screenshot:
CodePudding user response:
In the tokenValidationParameters
you set ValidateAudience = true
, which means that the aud
-claim will be checked. But you never set a value for ValidAudience
and also don't add an aud
-claim to the token.
You can either turn off the check by setting
ValidateAudience = false
or add a ValidAudience
like e.g:
ValidAudience = "your audience"
and add the aud
-claim with:
var jwt = new JwtSecurityToken(claims: claims,
audience: "your audience",
signingCredentials: signingCredentials,
expires: DateTime.Now.AddMinutes(30));