使用 Identity Server 4 (ASP.NET Core 3.1) 时,我无法验证某些集成测试请求。
我的设置如下:
身份服务器配置
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Email(),
new IdentityResources.Profile(),
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("resourceapi", "Resource API")
{
Scopes = {new Scope("api.read")}
}
};
}
public static IEnumerable<Client> GetClients()
{
return new[]
{
new Client
{
RequireConsent = false,
ClientId = "MY_CLIENT_ID",
ClientName = "My Client Name",
// code is required for SPA, client credentials for test runner
AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
AllowedScopes = {"openid", "profile", "email", "api.read"},
RedirectUris = {"http://localhost:4201/auth-callback"},
PostLogoutRedirectUris = {"http://localhost:4201/"},
AllowedCorsOrigins = {"http://localhost:4201"},
AllowAccessTokensViaBrowser = true,
AccessTokenLifetime = 3600,
RequireClientSecret = false
}
};
}
services.AddIdentity<AppUser, IdentityRole>()
.AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();
services.AddIdentityServer()
.AddDeveloperSigningCredential()
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder => builder.UseSqlServer(Configuration.GetConnectionString("Default"));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30; // interval in seconds
})
//.AddInMemoryPersistedGrants()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddAspNetIdentity<AppUser>();
ASP.NET Core 客户端
// this is called from Startup.ConfigureServices
public static void ConfigureSecurity(this IServiceCollection services, IConfiguration configuration)
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
o.Authority = configuration.GetSection("Idam").GetValue<string>("BaseUrl"); // http://localhost:54916
o.Audience = configuration.GetSection("Idam").GetValue<string>("Audience"); // "resourceapi"
o.RequireHttpsMetadata = false;
});
services.AddAuthorization();
}
集成测试代码
var client = new HttpClient();
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = $"{IdentityServerUrl}/connect/token",
ClientId = "MY_CLIENT_ID",
ClientSecret = IdentityServerPass,
Scope = "api.read"
}).ConfigureAwait(false);
tokenResponse.HttpResponse.EnsureSuccessStatusCode();
在这里,我收到一个不记名令牌,但似乎不被接受(身份服务器发出以下错误)。它如下所示:
{
"nbf": 1587392198,
"exp": 1587395798,
"iss": "http://localhost:54916",
"aud": "resourceapi",
"client_id": "STACKOVERFLOW_METRO_MIRROR",
"scope": [
"api.read"
]
}
> IdentityServer4.Hosting.IdentityServerMiddleware: Information:
> Invoking IdentityServer endpoint:
> IdentityServer4.Endpoints.TokenEndpoint for /connect/token
> IdentityServer4.Validation.TokenRequestValidator: Information: Token
> request validation success, { "ClientId":
> "STACKOVERFLOW_METRO_MIRROR", "ClientName": "My Client Name",
> "GrantType": "client_credentials", "Scopes": "api.read", "Raw": {
> "grant_type": "client_credentials",
> "scope": "api.read",
> "client_id": "MY_CLIENT_ID",
> "client_secret": "***REDACTED***" } } Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request
> starting HTTP/1.1 GET
> http://localhost:44324/api/GeneralData/GetAllTags
> Microsoft.AspNetCore.ResponseCaching.ResponseCachingMiddleware:
> Information: No cached response available for this request.
> Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:
> Information: Authorization failed.
> Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:
> Information: AuthenticationScheme: Bearer was challenged.
由于我的设置还包括一个能够成功进行身份验证的 SPA(通过 Identity Server 登录表单登录 -> 获取令牌 -> API 成功使用令牌),我解密了这样一个令牌,看看我是否看到任何可能揭示什么的相关差异我缺少测试身份验证流程:
{
"nbf": 1587393059,
"exp": 1587396659,
"iss": "http://localhost:54916",
"aud": "resourceapi",
"client_id": "MY_CLIENT_ID",
"sub": "fd351b3b-dfb2-4f2f-8987-af9d23c9dc6e",
"auth_time": 1587393055,
"idp": "local",
"given_name": "test",
"email": "test@example.com",
"scope": [
"openid",
"email",
"profile",
"api.read"
],
"amr": [
"pwd"
]
}
ASP.NET Core Web API Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.ConfigureCustomServices();
services.ConfigureSettings(Configuration);
services.ConfigureSecurity(Configuration);
services.ConfigureMvc();
services.BindLogging();
services.ConfigureRedisCache(Configuration);
services.ConfigureApiExplorer();
services.AddHttpContextAccessor();
services.AddDbContext(Configuration);
ConfigureAuditNet();
services.AddCorsAndPolicy();
services.ConfigureHangfire(Configuration);
services.AddSignalR();
services.AddAutoMapper(typeof(QuestionProfile).Assembly);
services.AddHealthChecks();
services
.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
ILoggingService logger, IHostApplicationLifetime lifetime, IServiceProvider serviceProvider,
ISoApiDailyRequestInfoService soApiDailyRequestInfoService)
{
app.UseResponseCaching();
app.UseMiddleware<ResponseTimeMiddleware>();
app.ProtectHangfireDashboard();
app.ConfigureExceptionPage(env);
app.StartHangFireJobs(serviceProvider, Configuration);
ConfigureApplicationLifetime(logger, lifetime, soApiDailyRequestInfoService);
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("CorsPolicy");
app.UseAuthentication();
app.UseAuthorization();
app.EnsureAppUserMiddleware();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<PostHub>("/post");
endpoints.MapHealthChecks("/health");
});
app.ConfigureAuditMiddleware();
app.UseSwagger();
}
不幸的是,身份服务器提供了一个非常普遍的错误,我确实看到了我在这里遗漏的内容。
问题:身份服务器发出AuthenticationScheme: Bearer was challenged
由客户端凭据获得的令牌。如何找出潜在的错误?