发送用户 ID 和 access_token

Posted

技术标签:

【中文标题】发送用户 ID 和 access_token【英文标题】:Sending user Id along with access_token 【发布时间】:2019-02-13 06:29:21 【问题描述】:

我正在使用 React 前端的 ASP.NET Core 2.1 应用程序中实现 Auth0。

一旦用户进行身份验证,我就会得到一个access_token 和一个id_token。我很清楚access_token 的目的是授予对我的 API 方法的访问权限。我也知道id_token 提供了我可以在我的前端应用程序中使用的用户数据。

问题/担忧是关于在我进行 API 调用时将用户数据(例如 userId)发送到我的后端。除了在我的 POST 请求的正文中包含 userId 之外,还有其他方法可以将其发送到我的 API 方法吗?

在 Auth0 之前,我使用了其他几个解决方案,我从他们那里收到的 JWT token 总是包括 userIdusername 等。我认为这是一种更安全的方法,因为即使人们可以看到是什么在JWT token 中,签名允许我们确保数据不被篡改。

尽管我的 API 调用是通过 SSL 保护的,但与通过 JWT token 发送它相比,我觉得在我的请求正文中包含进行 API 调用的人的 userId 不太安全。

我在这里遗漏了什么,还是我们确实通过 API 调用中的常规方式发送 userId,即在 POST 调用的正文中或在 GET 调用的查询字符串中?

【问题讨论】:

从访问令牌中获取用户信息。您只需通过指定范围(例如openid profile)来指定要从身份提供者那里获得的声明。然后,通常会在 api 项目中使用 User.Claims 访问声明。 sub 声明是用户 ID。 【参考方案1】:

好问题,我上周遇到了同样的问题,最后用同样的JWTAccessToken 解决了。

问题在于,在生成可以在服务器中检索的访问令牌时,将经过身份验证的用户的 UserId 添加为声明。

为访问令牌添加声明

首先将用户的 ID 添加到您的声明列表中。

List<Claim> claims = new List<Claim>();
claims.Add(new Claim("UserId", user.Id.ToString()));

然后生成访问令牌。

SecurityToken token = new JwtSecurityToken(
                        issuer: YOUR_ISSUER,
                        audience: YOUR_AUDIENCE,
                        claims: claims,
                        notBefore: DateTime.UtcNow,
                        expires: DateTime.UtcNow.AddMinutes(60),
                        signingCredentials: credentials
                     );

假设您已经知道如何在生成最终令牌之前执行这些步骤,这些步骤是从您在上面的问题中显示的 oAuthJWT 的能力中扣除的。

从访问令牌中检索声明

要从他们的 access_token 中读取 UserId,让我们创建几个帮助程序/扩展方法来帮助我们从控制器的 RequestContext 中读取 access_token。

public static string GetUserId(this ControllerBase controller)

    string securityKey = "YOUR_SECURITY_KEY";
    SymmetricSecurityKey key = new SymmetricSecurityKey(new UTF8Encoding().GetBytes(securityKey));
    JwtSecurityTokenHandler token_handler = new JwtSecurityTokenHandler();

    var tokenValidationParams = new TokenValidationParameters
    
        ValidateAudience = false,
        ValidateIssuer = false,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = key,
        ValidateLifetime = false
    ;

    string bearer = controller.HttpContext.Request.Headers["Authorization"].ToString().Replace("Bearer", string.Empty).Trim(' ');

    List<Claim> claims = token_handler.ValidateToken(bearer, tokenValidationParams, out SecurityToken token).Claims.ToList();

    Claim userClaim = claims.FirstOrDefault(x => x.Type == "UserId");

    if(userClaim != null)
    
        return userClaim.Value;
    
    else
    
        throw new Exception("Invalid AccessToken. UserId claim not found");
    

如何使用

现在让我们使用它在我们的任何控制器中获取 UserId

[Authorize]
public class ExampleController : Controller

    public IActionResult Index()
    
        string userId = this.GetUserId();

        // --> continuing code goes here.
    

【讨论】:

我实际上是在生成令牌的 Auth0 服务的上下文中说的。不过,我感谢您的回答并接受了它。话虽如此,在 Auth0 服务中可以通过“规则”向access_token 添加自定义声明。我能够在access_token 中包含用户 ID、名字、姓氏和用户的电子邮件地址。 Auth0 正在生成 access_token,因此您答案的第一部分是无关紧要的。至于答案的第二部分,JwtBearer 身份验证处理程序将为您完成所有这些工作,并且声明将在 ClaimsPrincipal HttpContext.User 上可用(在 ControllerBase.User 中引用)。 UserId 可以通过对var id = User.Claims.FirstOrDefault(x =&gt; x.Type == "userId"); 的简单调用在控制器中访问。这不应该是一个公认的答案。

以上是关于发送用户 ID 和 access_token的主要内容,如果未能解决你的问题,请参考以下文章

Discord.py 向自定义 ID 用户发送 DM

Firebase 通知和用户 ID

请问一下,C# js里面文本框的改变事件怎么写(主要是实现给用户发送信息,绑定2个文本框,一个存id)

F4 workerman 长连接绑定用户id实现一对一客服聊天

使用nodejs中的用户对象登录后将重新生成的会话ID发送回用户代理

在方法中发送 userID 或发送 Token