在 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);
我从发现文档端点找到了模数和指数,并使用它们来创建密钥。
我在后端 .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 };
}
}
}
}
问题是,验证总是失败。它给出了一个例外。
谢谢CB_Ron and juunas。将您的建议作为答案发布以帮助其他社区成员。
RsaSha256/RSA256
不是受支持的对称算法。你需要尝试对称算法,比如 SecurityAlgorithms.HmacSha256
.
可以参考Code Samples for Microsoft Identity Platform,
这是我尝试过的,对我有帮助
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);
我从发现文档端点找到了模数和指数,并使用它们来创建密钥。