我有3个项目1-Angular SPA 2-Web API项目核心3.1,3-带有核心3.1的IdentityServer 但我收到以下错误
> www-authenticate: Bearer error="invalid_token", error_description="The audience 'empty' is invalid"
这是我的 API 启动
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();
}
身份服务器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."),
};
}
}
身份服务器启动.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 配置
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
});
我有3个控制器,我在每个控制器上添加了[授权]。 谁能帮我这个?我成功生成了令牌,当我使用令牌调用 webapi 时,它会抛出 401 消息。但里面没有观众。
我面临同样的问题,并且?我的令牌中缺少 Aud 和 Iss。我需要它,因为在我的 Startup.cs 文件中,我将它们设置为验证所需的。
在您的令牌字符串中我没有看到Aud声明。
请参阅下面的两个代码:
Startup.cs中的ConfigureServices方法
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
};
});
以下是我的生成令牌方法:
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);
}
通过在以下位置添加行
ValidateAudience = false
来关闭受众验证:
.AddJwtBearer("Bearer", options =>
{
options.Authority = "https://localhost:5002/";
options.RequireHttpsMetadata = false;
options.Audience = "Api";
options.ValidateAudience = false;
});
对我来说,我必须删除以下内容
//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");
// });
//});
并添加以下代码。注意 ValidateAudience = false。这就是不同之处。
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,
};
});