'.net core 3.1 Bearer error="invalid_token", error_description="The audience 'empty' is invalid"
I have 3 projects 1- Angular SPA 2- Web API Project core 3.1, 3- IdentityServer with Core 3.1 But I am getting following error
> www-authenticate: Bearer error="invalid_token", error_description="The audience 'empty' is invalid"
This is my API startup
public void ConfigureServices(IServiceCollection services)
{
services.Configure<SchemaRegistryConfig>(Configuration.GetSection("SchemaRegistryConfig"));
//identity server
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer("Bearer", options =>
{
options.Authority = "https://localhost:5002/";
options.RequireHttpsMetadata = false;
options.Audience = "Api";
});
IdentityModelEventSource.ShowPII = true;
services.AddCors(c =>
{
c.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
});
services.AddMvc(config =>
{
config.Filters.Add(typeof(UnhandledExceptionFilter));
config.EnableEndpointRouting = false;
}).SetCompatibilityVersion(CompatibilityVersion.Latest);
services.AddServices(Configuration);
services.AddHealthChecksUI();
}
[Obsolete]
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors("AllowOrigin");
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseHttpsRedirection();
app.UseMvc();
}
Identity server config.cs
public static class Config
{
public static IEnumerable<IdentityResource> IdentityResources =>
new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Email(),
new IdentityResources.Profile(),
new IdentityResources.Address(),
new IdentityResource
{
Name = "Api",
//UserClaims =
//{
// "rc.garndma"
//}
}
};
public static IEnumerable<Client> Clients =>
new Client[]
{
new Client
{
ClientName = "Code Flow with refresh tokens",
ClientId = "_client",
AccessTokenLifetime = 330,// 330 seconds, default 60 minutes
IdentityTokenLifetime = 45,
AllowAccessTokensViaBrowser = true,
RedirectUris = new List<string>
{
"http://localhost:4200/*******"
},
PostLogoutRedirectUris = new List<string>
{
"http://localhost:4200/*******"
},
AllowedCorsOrigins = new List<string>
{
"http://localhost:4200"
},
RequireClientSecret = false,
AllowedGrantTypes = GrantTypes.Code,
RequirePkce = true,
AllowedScopes = { "openid", "profile", "email", "Api" },
AllowOfflineAccess = true,
RefreshTokenUsage = TokenUsage.OneTimeOnly
},
};
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("Api", "Invoice API")
{
Scopes = { "invoice.read", "invoice.pay", "manage" }
},
};
}
public static List<ApiScope> ApiScopes()
{
return new List<ApiScope> {
new ApiScope(name: "read", displayName: "Reads your invoices."),
new ApiScope(name: "pay", displayName: "Pays your invoices."),
};
}
}
identity server startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryApiScopes(Config.ApiScopes())
.AddInMemoryClients(Config.Clients)
.AddTestUsers(TestUsers.Users);
services.AddAuthentication();
services.AddCors(options => options.AddPolicy("AllowAll", p =>
p.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()));
// not recommended for production - you need to store your key material somewhere secure
builder.AddDeveloperSigningCredential();
}
public void Configure(IApplicationBuilder app)
{
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseCors("AllowAll");
app.UseIdentityServer();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
Angular SPA oidc config
export function configureAuth(oidcConfigService: OidcConfigService) {
return () =>
oidcConfigService.withConfig({
stsServer: 'https://localhost:5002',
redirectUrl: "http://localhost:4200/home",
postLogoutRedirectUri: window.location.origin,
clientId: '_client',
scope: 'openid profile email offline_access Api',
responseType: 'code',
silentRenew: true,
useRefreshToken: true
});
I have 3 controllers and I added [Authorize] on each controller. Can anyone help me with this? I get the token generated successfully and when I am using the token to call the webapi it throwing 401 with message. But no audience is present in it.
Solution 1:[1]
I was facing the same issue, and ?I was missing Aud and Iss in my token. I needed that since in my Startup.cs file, I set them to be required for validation.
In your token string I don't see Aud claim.
Please see both codes below:
ConfigureServices method in Startup.cs
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuer = true,
--> ValidateAudience = true, <--
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:SecretKey"])),
ClockSkew = TimeSpan.Zero
};
});
Below is my generate token method:
private string GenerateToken(UserViewModel loginViewModel)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SecretKey"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, loginViewModel.UserName),
new Claim("fullName", loginViewModel.FirstName + " " + loginViewModel.LastName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Aud, _configuration["Jwt:Audience"]),
new Claim(JwtRegisteredClaimNames.Iss, _configuration["Jwt:Issuer"])
};
var token = new JwtSecurityToken(
issuer: _configuration["Issuer"],
audience: _configuration["Audience"],
claims: claims,
expires: DateTime.Now.AddMonths(2),
signingCredentials: credentials
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
Solution 2:[2]
For me, I had to remove the following
//services.AddAuthentication("Bearer")
// .AddIdentityServerAuthentication("Bearer", options =>
// {
// options.Authority = identityServerUrl;
// options.RequireHttpsMetadata = false;
// options.ApiName = "bankOfDotNetApi";
// //options.TokenValidationParameters = new TokenValidationParameters();
// });
//services.AddAuthorization(options =>
//{
// options.AddPolicy("bankOfDotNetApi", policy =>
// {
// policy.RequireAuthenticatedUser();
// policy.RequireClaim("scope", "bankOfDotNetApi");
// });
//});
and add the following code. Note ValidateAudience = false. That made the difference.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.Authority = identityServerUrl;
options.RequireHttpsMetadata = false;
options.Audience = "bankOfDotNetApi";
options.TokenValidationParameters = new TokenValidationParameters
{
////////////////////////////////////////////////////////
// The following made the difference.
////////////////////////////////////////////////////////
ValidateAudience = false,
};
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | r2018 |
| Solution 2 | VivekDev |


