在 Azure 门户 > 应用程序注册中注册应用程序后,从 UI 生成的 .net core 3.1 API 项目中的令牌验证失败

Token validation fails in .net core 3.1 API project which is generated from the UI,after registrating the application in Azure Portal>App registration

我在后端 .NET core 3.1 项目中添加了一个中间件来处理令牌验证。

Startup.cs 变化

app.UseRouting();
app.UserAuthorization();
app.UserMiddleware<JWTMiddleware>();

JWTMiddleware.cs

    using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WebAPI
{
    public class JwtMiddleware
    {
        private readonly RequestDelegate _next;
        //private readonly AppSettings _appSettings;

        //public JwtMiddleware(RequestDelegate next, IOptions<AppSettings> appSettings)
        public JwtMiddleware(RequestDelegate next)
        {
            _next = next;
            //_appSettings = appSettings.Value;
        }

        public async Task Invoke(HttpContext context)
        {
            var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();

            if (token != null)
                await attachAccountToContext(context, token);

            await _next(context);
        }

        private async Task attachAccountToContext(HttpContext context, string token)
        {
            try
            {
                var tokenHandler = new JwtSecurityTokenHandler();
                var secretkey="";
                var key = Encoding.ASCII.GetBytes(secretKey);
                var clientID = "MYCLIENTID";
                tokenHandler.ValidateToken(token, new TokenValidationParameters
                {
                    ValidIssuer= "https://login.microsoftonline.com/MYTENNANTID/v2.0",
                    ValidAudience=clientID,
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    
                    ClockSkew = TimeSpan.Zero,
                    
                }, out SecurityToken validatedToken);

                var jwtToken = (JwtSecurityToken)validatedToken;
                var accountId = int.Parse(jwtToken.Claims.First(x => x.Type == "upn").Value);

                // attach account to context on successful jwt validation
                context.Items["Account"] = accountId;
            }
            catch(Exception ex)
            {

                // do nothing if jwt validation fails
                // account is not attached to context so request won't have access to secure routes
            }
        }
    }
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class AuthorizeAttribute : Attribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            var UserId = context.HttpContext.Items["Account"];
            if (UserId == null)
            {
                // not logged in
                context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
            }
        }
    }
}

问题是,验证总是失败。它给出了一个例外。

我在哪里可以找到钥匙。 我已经在 Azure 门户中添加了应用程序,并获得了一个 clientID 并创建了一个秘密。 之后,我使用这些详细信息在 UI 上生成一个令牌,并将其添加到授权 header 中并将其传递给应该对其进行验证的 API 项目。 我知道创建 IssuerSigningKey 的方式有问题,但无法弄清楚它是什么。我试过将秘密作为密钥传递,但效果不佳。

谢谢CB_Ron and juunas。将您的建议作为答案发布以帮助其他社区成员。

RsaSha256/RSA256 不是受支持的对称算法。你需要尝试对称算法,比如 SecurityAlgorithms.HmacSha256.

可以参考Code Samples for Microsoft Identity Platform, , and

这是我尝试过的,对我有帮助

var tokenHandler = new JwtSecurityTokenHandler();
            string secretKey = _configuration.GetValue<string>("AzureSSO:Secret");
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.ImportParameters(
              new RSAParameters()
              {
                  Modulus = FromBase64Url(_configuration.GetValue<string>("AzureSSO:Modulus")),
                  Exponent = FromBase64Url(_configuration.GetValue<string>("AzureSSO:Exponent"))
              });
            var clientID = _configuration.GetValue<string>("AzureSSO:ClientID");
            tokenHandler.ValidateToken(token, new TokenValidationParameters
            {
                ValidIssuer= _configuration.GetValue<string>("AzureSSO:Issuer"),
                ValidAudience=clientID,
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new RsaSecurityKey(rsa),
                ValidateIssuer = false,
                ValidateAudience = false,
                ClockSkew = TimeSpan.Zero,
                
            }, out SecurityToken validatedToken);

我从发现文档端点找到了模数和指数,并使用它们来创建密钥。