【发布时间】:2021-01-17 17:38:37
【问题描述】:
我正在使用 Identity Server 4 和 dotnetcore 3.1 构建 React SPA。 Identity Server 客户端使用IdentityServerSPA 配置文件在appsettings.json 中定义。在前端使用oidc-client,我可以成功登录。检查oidc 对象,我可以确认:
- token_type:
Bearer - 范围:
openid profile OpenWorkShopAPI - profile.sub:(我的用户 ID)
- profile.name:(我的用户名)
如果我随后尝试调用 API(使用 Authorization: Bearer 作为 id_token 或 access_token),则不存在 sub 声明。因此,_userManager.GetUserAsync(User); 失败。
枚举和打印声明,我明白了:
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-client 能够成功地看到用户 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);
});
【问题讨论】:
标签: .net-core asp.net-identity identityserver4 openid-connect