Asp.net核心6 mvc:使用外部API的JWT令牌授权控制器方法



我正在构建一个.Net core 6 mvc网站,该网站将与外部构建的API进行交互。除其他事项外,用户身份验证由API处理。一旦用户通过身份验证,API将使用JWT承载令牌进行响应,我需要将其绑定到我的网站以授权控制器方法。

在这一点上,我调用了API,并按预期成功地收到了令牌,然而,经过几天的努力,我完全迷失了方向,希望得到一些指导。在废除了多次代码迭代之后,这就是我目前所拥有的。。。。(原谅混乱(

public async Task<TokenResponse> LoginAsync(string email, string password)
{
var userLogin = new UserLogin
{
Email = email,
Password = password
};
string encoded = System.Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(email + ":" + password));
var client = new RestClient("api location");
var request = new RestRequest();
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Authorization", "Basic " + encoded);
var response = await client.GetAsync(request);
var result = JsonConvert.DeserializeObject<TokenResponse>(response.Content);
return result;
} 
public async Task<IActionResult> LoginPostAsync(LoginViewModel viewModel)
{
var tokenResponse = await _userManagementService
.LoginAsync(viewModel.Email, viewModel.Password);
if (!string.IsNullOrEmpty(tokenResponse.access_token))
{

var handler = new JwtSecurityTokenHandler();
var jwtSecurityToken = handler.ReadJwtToken(tokenResponse.access_token);
var jti = jwtSecurityToken.Claims.First(claim => claim.Type == "jti").Value;
var account_type = jwtSecurityToken.Claims.First(claim => claim.Type == "account_type").Value;
var userId = jwtSecurityToken.Claims.First(claim => claim.Type == "user_id").Value;
var email = jwtSecurityToken.Claims.First(claim => claim.Type == "email").Value;
var iss = jwtSecurityToken.Claims.First(claim => claim.Type == "iss").Value;
string[] userRoles = { "admin", "candidate",};
HttpContext context = new DefaultHttpContext();
var accessToken = tokenResponse.access_token;
//var userClaims = new List<Claim>()
//     {
//         new Claim("email", email),
//         new Claim("account_type", account_type),
//         new Claim("jti", jti),
//      };
//var userIdentity = new ClaimsIdentity(userClaims, "User Identity");
//var userPrincipal = new ClaimsPrincipal(new[] { userIdentity });
//context.SignInAsync(userPrincipal);
//Response.Cookies.Append(
//    Constants.XAccessToken,
//    tokenResponse.access_token, new CookieOptions
//    {
//        Expires = DateTimeOffset.UtcNow.AddMinutes(1),
//        HttpOnly = true,
//        SameSite = SameSiteMode.Strict
//    });
//return new AuthenticateResponse(user, token);
SetJWTCookie(accessToken);
return RedirectToAction("index", "Home", new { area = "CandidateDashboard" });
}
return Unauthorized();
}

程序.cs

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(config =>
{
config.SaveToken = true;
config.RequireHttpsMetadata = false;
config.TokenValidationParameters = new TokenValidationParameters()
{
ValidateAudience = false,
ValidateIssuer = true,
ValidIssuer = "issue data",
ValidateIssuerSigningKey = false,
};
config.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
context.Token = context.Request.Cookies["Bearer"];
return Task.CompletedTask;
}
};
});
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public IActionResult Index()
{
return View();
}
This is the what I see in dev console. 
--bearer error="invalid_token", error_description="the signature key was not found" 

来自承载的有效载荷

{
"iss": "data here",
"exp": 1647323406,
"nbf": 1647319746,
"iat": 1647319806,
"jti": "e8f297d3-blah blah",
"account_type": "candidate",
"user_id": "2342342342",
"email": "email@email.com"
}

核心问题是AddJwtBearer默认情况下只信任它信任的人(发行人(发行的令牌,因为它需要验证令牌的签名。你当然想验证它,这样黑客就不会向你的API发送伪造的代币。

所以要么你需要添加

.AddJwtBearer(opt =>
{
opt.Authority = "https://issuer.com"

通过这种方式,AddJwtBearer将自动为您下载公共签名密钥。

或者您需要手动将公共签名密钥添加到AddJwtBearer中。看见https://devblogs.microsoft.com/dotnet/jwt-validation-and-authorization-in-asp-net-core/

为了补充这个答案,我写了一篇博客文章,详细介绍了这个话题:ASP.NET Core 中JwtBearer身份验证问题的疑难解答

最新更新