IdentityServer 4间歇性返回从内省端点返回的错误导致401

时间:2018-03-01 11:47:49

标签: c# asp.net-core identityserver4

我们在生产中使用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

  • 使用AspCoreIdentity over https
  • 的IdentityServer引用令牌
  • 基于https的AspCore MVC应用程序/ Web API
  • 基于https的AspCore Web API

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;
            });

0 个答案:

没有答案