我正在使用React前端在我的ASP.NET Core 2.1应用程序中实现Auth0。
一旦用户验证,我得到access_token
和id_token
。我很清楚access_token
的目的是授予访问我的API方法的权限。我也明白id_token
提供了我可以在我的前端应用程序中使用的用户数据。
问题/关注是关于在我进行API调用时将用户数据(例如userId
)发送到我的后端。除了在userId
请求的正文中包含POST
之外,还有另一种方法将它发送到我的API方法吗?
在Auth0之前,我使用了其他一些解决方案,我从他们那里收到的JWT token
总是包括userId
,username
等。我认为这是一种更安全的方法,因为即使可以看到JWT token
中的内容,签名也允许我们确保数据没有变通。
即使我的API调用是通过SSL
保护的,我觉得包括在我的请求正文中进行API调用的人的userId
与通过JWT token
发送它相比不太安全。
我在这里遗漏了什么,或者我们确实在API调用中通过常规方式发送userId
,即在POST
调用的主体中或在GET
调用的查询字符串中?
好问题的人,我上周经历了同样的问题,并最终使用相同的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
);
我假设您已经知道如何在达到最终令牌生成之前执行这些步骤,这是从您在问题中显示的oAuth
和JWT
的实力中扣除的。
从访问令牌中检索声明
要从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.
}
}