Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net core UserID子声明已生成,但从Identity Server 4令牌中消失,导致UserManager.GetUser失败_.net Core_Asp.net Identity_Identityserver4_Openid Connect - Fatal编程技术网

.net core UserID子声明已生成,但从Identity Server 4令牌中消失,导致UserManager.GetUser失败

.net core UserID子声明已生成,但从Identity Server 4令牌中消失,导致UserManager.GetUser失败,.net-core,asp.net-identity,identityserver4,openid-connect,.net Core,Asp.net Identity,Identityserver4,Openid Connect,我正在使用Identity Server 4和dotnetcore 3.1构建React SPA。Identity Server客户端是在appsettings.json中使用Identity Server SPA配置文件定义的。在前端使用oidc客户端,我可以成功登录。检查oidc对象,我可以确认: 令牌类型:承载方 范围:openid配置文件OpenWorkShopAPI profile.sub:(我的用户ID) profile.name:(我的用户名) 如果我随后尝试调用API(使用A

我正在使用Identity Server 4和dotnetcore 3.1构建React SPA。Identity Server客户端是在
appsettings.json
中使用
Identity Server SPA
配置文件定义的。在前端使用
oidc客户端
,我可以成功登录。检查
oidc
对象,我可以确认:

  • 令牌类型:
    承载方
  • 范围:
    openid配置文件OpenWorkShopAPI
  • profile.sub:(我的用户ID)
  • profile.name:(我的用户名)
如果我随后尝试调用API(使用
Authorization:Bearer
作为
id\u令牌
access\u令牌
),则不存在
sub
声明。因此,
\u userManager.GetUserAsync(用户)失败

列举并打印索赔,我看到:

Claim: "System.Security.Claims.ClaimsIdentity" "nbf" "1601597732"
Claim: "System.Security.Claims.ClaimsIdentity" "exp" "1601598032"
Claim: "System.Security.Claims.ClaimsIdentity" "iss" "http://dev.openwork.shop:5000"
Claim: "System.Security.Claims.ClaimsIdentity" "aud" "OpenWorkShopAPI"
Claim: "System.Security.Claims.ClaimsIdentity" "iat" "1601597732"
Claim: "System.Security.Claims.ClaimsIdentity" "at_hash" "MoAqNfND0ct1mUFKpUtgcg"
Claim: "System.Security.Claims.ClaimsIdentity" "s_hash" "D81HZF_ii2r0i5-4_ZxnLA"
Claim: "System.Security.Claims.ClaimsIdentity" "sid" "cdMH0nFKdikldL1Gy3S3Eg"
Claim: "System.Security.Claims.ClaimsIdentity" "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" "fdf0023d-7ae9-4aaf-87fe-0f320b869171"
Claim: "System.Security.Claims.ClaimsIdentity" "auth_time" "1601582136"
Claim: "System.Security.Claims.ClaimsIdentity" "http://schemas.microsoft.com/identity/claims/identityprovider" "local"
Claim: "System.Security.Claims.ClaimsIdentity" "http://schemas.microsoft.com/claims/authnmethodsreferences" "pwd"
基于此,我可以通过访问名称声明直接查找ID来解决此问题:

string CurrentUserId => User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
但这似乎既不正确也不理想

我注意到我所有的MySQL表(除了
AspNetUsers
)都是空的。例如,
AspNetUserClaims
中没有值。然而,正如我上面所展示的,
oidc客户端
能够成功地看到用户ID的
sub
声明

由于我使用的是
DefaultIdentity
AddApiAuthorization
,因此我不希望需要添加任何特殊的逻辑来实现这些子声明,也不确定为什么API调用中缺少它

配置:

services.AddDefaultIdentity<UserProfile>(options => {
        options.SignIn.RequireConfirmedAccount = true;
        options.SignIn.RequireConfirmedEmail = true;
        options.Stores.MaxLengthForKeys = 64;
      }).AddEntityFrameworkStores<OWSData>();

      WebHostOptions webHost = configuration.GetSection("WebHost").Get<WebHostOptions>();
      string root = webHost.Url;

      services.AddIdentityServer((options) => {
        options.PublicOrigin = root;
        options.IssuerUri = root;
        options.UserInteraction.LoginUrl = $"{root}/account/login";
        options.UserInteraction.LogoutUrl = $"{root}/account/logout";
        options.UserInteraction.ErrorUrl = $"{root}/account/error";
        options.UserInteraction.ConsentUrl = $"{root}/account/terms-of-service";
        options.UserInteraction.DeviceVerificationUrl = $"{root}/account/device-verification";
      }).AddApiAuthorization<UserProfile, OWSData>(options => {
        // Serilog.Log.Information("Clients: {@clients}", options.Clients);
      });
      services.AddScoped<ICurrentUser, CurrentUser>();
      services.AddTransient<IReturnUrlParser, AuthReturnUrl>();

      // Auth (JWT)
      services.AddAuthentication(options => {
                 // options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
               })
              .AddCookie((options) => {
                 webHost.ConfigureCookie(CookieName, options.Cookie);
                 options.LoginPath = "/account/login";
                 options.AccessDeniedPath = "/account/denied";
                 options.LogoutPath = "/account/logout";
                 options.SlidingExpiration = true;
               })
              .AddIdentityServerJwt()
              .AddGoogle(options => {
                 ConfigureOAuth(options, "Google", configuration, webHost);
               })
              .AddGitHub(options => {
                 ConfigureOAuth(options, "GitHub", configuration, webHost);
                 options.Scope.Add("user:email");
                 options.EnterpriseDomain = configuration["GitHub:EnterpriseDomain"];
               });

      services.AddAuthorization(options => {
        // options.DefaultPolicy = new AuthorizationPolicy();
      });

      // Auth (Password)
      services.Configure<IdentityOptions>(options => {
        //Password settings
        options.Password.RequireDigit = true;
        options.Password.RequireLowercase = true;
        options.Password.RequireNonAlphanumeric = true;
        options.Password.RequireUppercase = true;
        options.Password.RequiredLength = 6;
        options.Password.RequiredUniqueChars = 1;

        //Lockout settings
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
        options.Lockout.MaxFailedAccessAttempts = 5;
        options.Lockout.AllowedForNewUsers = true;

        //User settings
        options.User.AllowedUserNameCharacters =
          "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@";
        options.User.RequireUniqueEmail = false;
      });

      // Cookies
      services.ConfigureApplicationCookie(options => {
        webHost.ConfigureCookie(CookieName, options.Cookie);
      });
services.AddDefaultIdentity(选项=>{
options.SignIn.RequireConfirmedAccount=true;
options.SignIn.RequireConfirmedEmail=true;
options.Stores.MaxLengthForKeys=64;
}).AddEntityFrameworkStores();
WebHostOptions webHost=configuration.GetSection(“webHost”).Get();
stringroot=webHost.Url;
services.AddIdentityServer((选项)=>{
options.PublicOrigin=root;
options.IssuerUri=根目录;
options.UserInteraction.LoginUrl=$“{root}/account/login”;
options.UserInteraction.LogoutUrl=$“{root}/account/logout”;
options.UserInteraction.ErrorUrl=$“{root}/account/error”;
options.UserInteraction.approveURL=$“{root}/account/terms of service”;
options.UserInteraction.DeviceVerificationUrl=$“{root}/帐户/设备验证”;
}).addapi授权(选项=>{
//Serilog.Log.Information(“Clients:{@Clients}”,options.Clients);
});
services.addScope();
services.AddTransient();
//认证(JWT)
services.AddAuthentication(选项=>{
//options.DefaultAuthenticateScheme=CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie((选项)=>{
ConfigureCookie(CookieName,options.Cookie);
options.LoginPath=“/account/login”;
options.AccessDeniedPath=“/account/denied”;
options.LogoutPath=“/account/logout”;
options.SlidingExpiration=true;
})
.AddIdentityServerJwt()
.AddGoogle(选项=>{
配置OAuth(选项“谷歌”、配置、网络主机);
})
.AddGitHub(选项=>{
配置OAuth(选项“GitHub”、配置、webHost);
options.Scope.Add(“用户:电子邮件”);
options.EnterpriseDomain=配置[“GitHub:EnterpriseDomain”];
});
services.AddAuthorization(选项=>{
//options.DefaultPolicy=新授权策略();
});
//认证(密码)
配置(选项=>{
//密码设置
options.Password.RequireDigit=true;
options.Password.RequireLowercase=true;
options.Password.RequireNonAlphanumeric=true;
options.Password.RequireUppercase=true;
options.Password.RequiredLength=6;
options.Password.RequiredUniqueChars=1;
//锁定设置
options.Lockout.DefaultLockoutTimeSpan=TimeSpan.FromMinutes(5);
options.locket.MaxFailedAccessAttempts=5;
options.locket.AllowedForNewUsers=true;
//用户设置
options.User.AllowedUserName字符=
“ABCDEFGHIJKLMNOPQRSTUVWXYZABDEFGHIJKLMNOPQRSTUVXYZ0123456789-。”;
options.User.RequireUniqueEmail=false;
});
//饼干
services.configureApplicationOK(选项=>{
ConfigureCookie(CookieName,options.Cookie);
});

JwtBearerAuthentication
中间件上的
JwtSecurityTokenHandler
默认情况下映射了一些声明。沿着这些映射,
sub
声明被映射到
ClaimTypes.NameIdentifier
。将列出映射

您可以更改API上的代码,将名称标识符声明设置为
NameClaimType
NameClaimType
用于设置
Identity.Name

以下是API所需的代码更改:

services.AddAuthentication("Bearer").AddJwtBearer("Bearer",
                options =>
                {
                    options.Authority = "http://localhost:5000";
                    options.Audience = "api1";
                    options.RequireHttpsMetadata = false;

                    
                    options.TokenValidationParameters = new TokenValidationParameters()
                    {
                        NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"//To set Identity.Name 
                    };         
                });
下面是一个示例工作代码:

编辑:如果您使用
IdentityServerSPA
template来创建项目,那么它只是一个具有一些扩展方法的模板,内部使用的方法与我们在手动设置中使用的方法相同

例如,per
IdentityServerJwt
将执行以下操作:

表示与IdentityServer一起托管的API。 应用程序配置为具有默认为应用程序名称的单个作用域

为了达到上述目的,需要在内部调用
AddJwtBearer

它还用于添加api资源

因此,如果我们使用手动设置或仅使用IDS4模板,我们可以在代码中看到调用

在这种情况下,由于您可以在扩展方法中调用它,因此您可以更改

services.Configure<JwtBearerOptions>("Bearer",
                options =>
                {
                    new TokenValidationParameters()
                    {
                        NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"//To set Identity.Name 
                    };
                });
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();