identityserver4 - 使用 Windows 身份验证的 IdentityServer4 委派 User.Identity.Name 为 null
问题描述
我有以下流程 Asp.Net Core App (App) 调用 Asp.Net Core Web API (API1) 又调用另一个 Asp.Net Web API (API2)
我正在使用带有 Windows 身份验证的 IdentityServer4 来验证我的用户,这是我的代码:
ApiResources 定义:
new ApiResource("api1", "api1", new List<string> { JwtClaimTypes.Name, JwtClaimTypes.Email}),
new ApiResource("api2", "api2", new List<string> { JwtClaimTypes.Name, JwtClaimTypes.Email})
客户定义
new Client
{
ClientId = "app1",
ClientName = "app1",
ClientSecrets = { new Secret("app1".Sha256())},
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.OfflineAccess,
IdentityServerConstants.StandardScopes.Email,
"api1"
},
RedirectUris = { "https://localhost:44375/signin-oidc" },
FrontChannelLogoutUri = "https://localhost:44375/signout-oidc",
PostLogoutRedirectUris = { "https://localhost:44375/signout-callback-oidc" },
AllowOfflineAccess = true,
RequireConsent = false,
AccessTokenLifetime = 5
},
new Client
{
ClientId = "api1",
ClientSecrets = { new Secret("api1".Sha256())},
AllowedGrantTypes = {"delegation" },
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"api2"}
}
API1 中的委托代码
public async Task<string> DelegateAsync(string userToken)
{
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("https://localhost:44382/");
if (disco.IsError) throw new Exception(disco.Error);
var tokenResponse = await client.RequestTokenAsync(new TokenRequest()
{
Address = disco.TokenEndpoint,
GrantType = "delegation",
ClientId = "api1",
ClientSecret = "api1",
Parameters =
{
{"scope" , "api2 email profile openid" },
{"token", userToken }
}
});
if (tokenResponse.IsError)
{
throw new Exception(tokenResponse.Error);
}
_logger.LogInformation($"new: {tokenResponse.AccessToken}");
return tokenResponse.AccessToken;
}
IdentityServer4 委托授权验证器:
public class DelegationGrantValidator : IExtensionGrantValidator
{
private readonly ITokenValidator _validator;
public DelegationGrantValidator(ITokenValidator validator)
{
_validator = validator;
}
public string GrantType => "delegation";
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
var userToken = context.Request.Raw.Get("token");
if (string.IsNullOrEmpty(userToken))
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
return;
}
var result = await _validator.ValidateAccessTokenAsync(userToken);
if (result.IsError)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
return;
}
// get user's identity
var sub = result.Claims.FirstOrDefault(c => c.Type == "sub").Value;
context.Result = new GrantValidationResult(sub, GrantType);
return;
}
}
在 API1User.Identity.Name = "Domain\UserName"
但在 API2User.Identity.Name = null
我应该解决这个问题吗?
PS:如果我从 API2 调用 IdentityServer UserInfo 端点,我将得到预期的 UserName
解决方案
经过大量搜索,我终于找到了答案。
我已经按照本文中描述的 Rory Braybrook 进行了操作,现在一切正常
推荐阅读
- python - 如何在 Azure Data Studio 中显示 IPython Notebook Output (Pandas Data Frame) 的所有列?
- raspberry-pi - 如何使用 Raspberry Pi 编写 SD/mmc 程序
- web-component - connectedCallback 中的自定义 Web 组件设置属性
- rust - 在 Rust 中使用 iodbc
- python - 如何在光栅图像中绘制轮廓或形状的偏移量?
- forms - 如何在表单输入字段中保存或存储数据。在反应原生提交表单后
- r - 具有来自 {gtsummary} 的 tbl_uvregression() 函数的多元单变量 Cox 回归
- docker - 带有 Docker 的超集无法添加到外部 mysql 的连接
- typescript - 我们可以根据道具的形状构建打字稿类型吗?
- python - MacOS中的Python Tkinter checkbutton小部件:如何设置文本颜色