我们在生产中使用IdentityServer4并且间歇性地获得“从内省端点返回错误:发送请求时发生错误。”。这反过来导致从MVC客户端和我们的Web API返回401。
日志设置为调试级别,但没有显示Introspection EndPoint失败原因的任何原因。我们在MVC客户端的日志中得到的是
2018-03-01 10:41:54.405 +00:00 [ERR] Error returned from introspection endpoint: An error occurred while sending the request.
2018-03-01 10:41:54.406 +00:00 [INF] BearerIdentityServerAuthenticationIntrospection was not authenticated. Failure message: Error returned from introspection endpoint: An error occurred while sending the request.
2018-03-01 10:41:54.406 +00:00 [INF] Bearer was not authenticated. Failure message: Error returned from introspection endpoint: An error occurred while sending the request.
2018-03-01 10:41:54.406 +00:00 [INF] Authorization failed for user: null.
设置是在IIS 8.5中托管的ASP.Net Core
IdentityServer
IdentityServer配置如下(我们将访问令牌设置为1天)
new Client
{
ClientId = "Redacted",
ClientName = "Redacted",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
AccessTokenType = AccessTokenType.Reference,
AccessTokenLifetime = 86400,
RequireConsent = false,
AllowAccessTokensViaBrowser = true,
ClientSecrets = new List<Secret>
{
new Secret("Redacted")
},
RedirectUris = new List<string>
{
$"{client}/signin-oidc"
},
PostLogoutRedirectUris = new List<string>
{
$"{client}/signout-callback-oidc"
},
AllowedCorsOrigins = new List<string>
{
client
},
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"roles",
"MonitoringInternalAPI",
"MonitoringAPI",
"MonitoringDialOutAPI",
"MonitoringAdminAPI"
},
UpdateAccessTokenClaimsOnRefresh = true,
AllowOfflineAccess = true
}
IdentityServer的设置
services.AddIdentityServer()
.AddSigningCredential(Configuration["IdentityServer:X509Thumbprint"],
StoreLocation.LocalMachine,
NameType.Thumbprint)
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients(Configuration.GetValue<string>("IdentityServer:Client"), Configuration.GetValue<int>("IdentityServer:AccessTokenLifetime")))
.AddAspNetIdentity<ApplicationUser>();
MVC应用
MVC应用程序使用cookie作为Razor视图和承载令牌,用于构建的API调用。我们还使用MemoryCacheTicketStore实现来存储角色。
IdentityServer设置
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultForbidScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies", options =>
{
options.SessionStore = new MemoryCacheTicketStore();
})
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = Configuration["IdentityServerClient:Authority"];
options.RequireHttpsMetadata = false;
options.ClientId = "Redacted";
options.ClientSecret = "Redacted";
options.ResponseType = "code id_token";
options.Scope.Add("openid");
options.Scope.Add("MonitoringInternalAPI");
options.Scope.Add("MonitoringAPI");
options.Scope.Add("MonitoringDialOutAPI");
options.Scope.Add("MonitoringAdminAPI");
options.Scope.Add("offline_access");
options.Scope.Add("roles");
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.Events = new OpenIdConnectEvents()
{
OnUserInformationReceived = (context) =>
{
ClaimsIdentity claimsId = context.Principal.Identity as ClaimsIdentity;
var roles = context.User.Children().FirstOrDefault(j => j.Path == JwtClaimTypes.Role).Values().ToList();
claimsId.AddClaims(roles.Select(r => new Claim(JwtClaimTypes.Role, r.Value<String>())));
return Task.FromResult(0);
}
};
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.Name,
RoleClaimType = JwtClaimTypes.Role
};
})
.AddIdentityServerAuthentication(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.Authority = Configuration["IdentityServerClient:Authority"];
options.EnableCaching = true;
options.CacheDuration = TimeSpan.FromSeconds(600);
options.ApiName = "MonitoringInternalAPI";
options.ApiSecret = "Redacted";
options.RequireHttpsMetadata = false;
});
Web API
Identity Server设置为
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = Configuration["IdentityServer:Authority"];
options.ApiName = "MonitoringAPI";
options.RoleClaimType = "role";
options.ApiSecret = "Redacted";
options.EnableCaching = true;
options.CacheDuration = TimeSpan.FromSeconds(600);
options.RequireHttpsMetadata = false;
});