C# 本地用户存储和oauth提供者之间的用户id如何关联?

C# 本地用户存储和oauth提供者之间的用户id如何关联?,c#,asp.net,oauth,asp.net-identity,asp.net-identity-3,C#,Asp.net,Oauth,Asp.net Identity,Asp.net Identity 3,我的背景 我正在尝试为ASP.NET标识创建自定义用户/角色存储 背景 关于在使用ASP.NET标识时获取用户id,这里有几个问题。它们中的大多数都是围绕解析NameIdentifier声明来解决的 然而,他们中的大多数人似乎忽略了一个重要点。使用OAuth时,NameIdentifier似乎指向OAuth提供程序返回的标识 这可以通过在身份验证完成后在AccountController中设置断点来观察 我的问题 如果查看UserStore,您可以看到GetUserIdAsync将返回Ident

我的背景

我正在尝试为ASP.NET标识创建自定义用户/角色存储

背景

关于在使用ASP.NET标识时获取用户id,这里有几个问题。它们中的大多数都是围绕解析
NameIdentifier
声明来解决的

然而,他们中的大多数人似乎忽略了一个重要点。使用OAuth时,
NameIdentifier
似乎指向OAuth提供程序返回的标识

这可以通过在身份验证完成后在AccountController中设置断点来观察

我的问题

如果查看UserStore,您可以看到
GetUserIdAsync
将返回
IdentityUser
对象的
Id
,该对象是数据库中的内部Id。到目前为止一切都很好

但是,如果您查看以下代码:

/// <summary>
/// Returns the User ID claim value if present otherwise returns null.
/// </summary>
/// <param name="principal">The <see cref="T:System.Security.Claims.ClaimsPrincipal" /> instance.</param>
/// <returns>The User ID claim value, or null if the claim is not present.</returns>
/// <remarks>The User ID claim is identified by <see cref="F:System.Security.Claims.ClaimTypes.NameIdentifier" />.</remarks>
public virtual string GetUserId(ClaimsPrincipal principal)
{
  if (principal == null)
    throw new ArgumentNullException("principal");
  return principal.FindFirstValue(this.Options.ClaimsIdentity.UserIdClaimType);
}
上面的代码将调用
UserStore.FindByIdAsync
,用户id为用户id。因此,用户存储将尝试使用不正确的密钥查找应用程序用户

一种方法是使用oAuth用户id作为本地用户表中的PK,但如果两个oAuth提供程序返回相同的id(可能性不大),这种方法可能会失败。当多个oauth标识与同一应用程序用户关联时,它也不起作用

我的问题


我做错什么了吗?应用程序用户存储和oauth提供程序之间的用户ID如何关联?

您不应该使用oauth提供程序的声明主体调用GetUserId。唯一应该与之一起使用的ClaimsPrincipal是通过identity使用的ClaimsPrincipalUserFactory生成的。将OAuth与本地用户关联通常通过AddLogin方法完成,该方法将OAuth id链接到本地用户id。

您不应该使用OAuth提供者的声明主体调用GetUserId。唯一应该与之一起使用的ClaimsPrincipal是通过identity使用的ClaimsPrincipalUserFactory生成的。将OAuth与本地用户关联通常通过AddLogin方法完成,该方法将OAuth id链接到本地用户id

//this returns the oauth id, can't be used to work with the application user
var id = await _userManager.GetUserIdAsync(currentClaimPrincipal);

//this returns null as it internally uses the above line
await user = _userManager.GetUserAsync(currentClaimPrincipal);