我已经实现了基于IdentityServer3的身份验证服务和一个简单的MVC客户端应用程序以及由身份验证服务保护的Shopper API。我已经实现了IdentityServer自定义UserService,以便身份验证服务对我们现有的用户数据存储进行身份验证。 My Shopper API需要Shopper Get请求中的用户ID。目前,来自身份验证服务的响应包括身份令牌和访问令牌,但没有用户ID。我尝试在自定义UserService.AuthenticateLocalAsync方法的AuthenticationResult中添加user_id声明,但我在客户端应用程序代码中没有看到它。 UserService.AuthenticateLocalAsync如下所示:
try
{
var user = new shopper(_dbConnLib, context.UserName, context.Password);
var claims = new List<Claim> { new Claim("user_id", user.shopperid) };
context.AuthenticateResult = new AuthenticateResult(user.shopperid, user.MemberDetail.billToAddress.FirstName, claims);
}
catch(shopperInitFromException ex)
{
context.AuthenticateResult = null; // Indicates username/password failure
}
return Task.FromResult(0);
我的客户端应用程序SecurityTokenValidated处理程序如下所示:
SecurityTokenValidated = async n =>
{
var nid = new ClaimsIdentity(
n.AuthenticationTicket.Identity.AuthenticationType,
Constants.ClaimTypes.GivenName,
Constants.ClaimTypes.Role);
var userInfoClient = new UserInfoClient(
new Uri(n.Options.Authority + "/connect/userinfo").ToString());
var userInfo = await userInfoClient.GetAsync(n.ProtocolMessage.AccessToken);
userInfo.Claims.ToList().ForEach(ui => nid.AddClaim(new Claim(ui.Type, ui.Value)));
nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));
//nid.AddClaim(new Claim("user_id", n.ProtocolMessage.UserId));
nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));
n.AuthenticationTicket = new AuthenticationTicket(
nid,
n.AuthenticationTicket.Properties);
}
如果我在调试器中单步调试,userInfo.Claims的计数总是为0.如何使用用户的唯一标识符取回声明?或者我可以从身份或访问令牌中获取它吗?或者我应该将令牌传递给Shopper API并让它从令牌中确定ID?
答案 0 :(得分:1)
我想我可能有答案。到目前为止,据我所知,我在AuthenticateLocalAsync的重写中包含在AuthenticateResult构造函数中的声明似乎无处可去。但是我在我的覆盖GetProfileDataAsync中包含的声明出现在令牌中。我的GetProfileDataAsync代码似乎正确设置了声明,如下所示:
public override Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var user = new shopper(_dbConnLib, context.Subject.FindFirst("sub").Value);
var claims = new List<Claim> { new Claim("sub", user.shopperid), new Claim("acr_level", "level 0"), new Claim("amr", "anonymous") };
context.IssuedClaims = claims;
return Task.FromResult(0);
}
我的AuthenticateLocalAsync代码在AuthenticateResult中设置我从未在客户端应用程序代码中看到的声明,如下所示:
public override Task AuthenticateLocalAsync(LocalAuthenticationContext context)
{
// TODO: Handle AddshopperToBasketException in UserService.AuthenticateLocalAsync
try
{
var user = new shopper(_dbConnLib, context.UserName, context.Password);
var claims = new List<Claim> { new Claim("acr_level", "level 0"), new Claim("amr", "anonymous") };
context.AuthenticateResult = new AuthenticateResult(user.shopperid, user.MemberDetail.billToAddress.FirstName, claims);
}
catch(shopperInitFromException ex)
{
context.AuthenticateResult = null; // Indicates username/password failure
}
return Task.FromResult(0);
}