使用 Windows 身份验证 User.Identity.Name 的 IdentityServer4 委派为空
IdentityServer4 Delegation With Windows Authentication User.Identity.Name is null
我有以下流程 Asp.Net Core App (App) 调用 Asp.Net Core Web API (API1) 又调用另一个 Asp.Net 网页 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 DelegationGrantValidator:
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;
}
}
在 API1 User.Identity.Name = "Domain\UserName"
但在 API2 User.Identity.Name = null
有什么遗漏我应该解决这个问题吗?
P.S.: 如果我从 API2 调用 IdentityServer UserInfo 端点,我将获得预期的 UserName
经过大量的搜索,我终于找到了答案。
我已遵循 Rory Braybrook 在 this Article 中描述的内容,现在一切正常
我有以下流程 Asp.Net Core App (App) 调用 Asp.Net Core Web API (API1) 又调用另一个 Asp.Net 网页 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 DelegationGrantValidator:
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;
}
}
在 API1 User.Identity.Name = "Domain\UserName"
但在 API2 User.Identity.Name = null
有什么遗漏我应该解决这个问题吗?
P.S.: 如果我从 API2 调用 IdentityServer UserInfo 端点,我将获得预期的 UserName
经过大量的搜索,我终于找到了答案。
我已遵循 Rory Braybrook 在 this Article 中描述的内容,现在一切正常