"IDX10511: Signature validation failed" 用于 Azure AD SPA 应用程序
"IDX10511: Signature validation failed" for Azure AD SPA application
我有一个源自 Identity Platform 示例的 SPA 应用程序,该示例最初调用图形 API。
我已将端点更改为调用本地 API。
SPA 使用 Azure AD 进行身份验证。
API 示例源自 API 的 VS 2019 项目模板。
、NET 4.7.2 - 没有 .NET Core。
我可以进行身份验证,并且在进行网络跟踪时 ID 和访问令牌都存在。
然而,在API这边我得到一个错误:
"IDX10511: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.X509SecurityKey, KeyId: '1E50B4475DAC931359D564309A3385FFAB7FB431', InternalId: 'f61f7746-3cff-4557-8b2c-b47fad9cf1e3'. , KeyId: 1E50B4475DAC931359D564309A3385FFAB7FB431"
解码访问令牌显示:
"{
"typ": "JWT",
"nonce": "G0Q6_BuYJUfZaBnX-l1Ox1eoncxXRT4KMThFBcn1-VA",
"alg": "RS256",
"x5t": "HlC0R12skxNZ1WQwmjOF_6t_tDE",
"kid": "HlC0R12skxNZ1WQwmjOF_6t_tDE"
}"
谷歌搜索,似乎签名失败是因为 header 中的随机数,这需要 "special processing".
所有验证都由 OWIN 完成。
知道这是什么或如何解决这个问题吗?
我认为这不是配置问题,因为我从未见过任何指定签名的配置。
所以我开始浏览 msal.js - 它是开源的。
"User.Read"(在我使用的示例中定义的范围)在许多地方被硬编码,所以我从示例中删除了这个范围并创建了一个名为 "abc".[=12 的虚拟范围=]
我还针对范围更改重新配置了 Azure AD。
瞧,一切正常。
更有趣的是,header是不同的:
{
"typ": "JWT",
"alg": "RS256",
"x5t": "HlC0R12skxNZ1WQwmjOF_6t_tDE",
"kid": "HlC0R12skxNZ1WQwmjOF_6t_tDE"
}
注意没有随机数。
所以我怀疑因为原始样本使用了 Microsoft Graph,"User.Read" 暗示了一些特殊的图形处理,添加了搞砸签名的随机数。
对于reference。
如果您仍然需要 User.Read 作用域,您可以通过添加一个在身份验证之前散列 nonce 的中间件来获得成功的签名验证
app.UseMiddleware<HashNonceJwtHeaderMiddleware>();
这里是中间件:
using System.IdentityModel.Tokens.Jwt;
using System.Security.Cryptography;
namespace MyApplication.Api.Infrastructure
{
public class HashNonceJwtHeaderMiddleware
{
private readonly RequestDelegate _next;
private static bool _hashNonceBeforeValidateToken = true;
public HashNonceJwtHeaderMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
string accessToken = context.Request.Headers["Authorization"].FirstOrDefault();
if (string.IsNullOrWhiteSpace(accessToken)) { return; }
accessToken = accessToken.Substring("Bearer ".Length);
var tokenHandler = new JwtSecurityTokenHandler();
var jsonToken = tokenHandler.ReadJwtToken(accessToken);
string[] parts = accessToken.Split('.');
string header = parts[0];
string payload = parts[1];
string signature = parts[2];
if (_hashNonceBeforeValidateToken &&
jsonToken.Header.TryGetValue("nonce", out object nonceAsObject))
{
string plainNonce = nonceAsObject.ToString();
using (SHA256 sha256 = SHA256.Create())
{
byte[] hashedNonceAsBytes = sha256.ComputeHash(
System.Text.Encoding.UTF8.GetBytes(plainNonce));
string hashedNonce = Encode(hashedNonceAsBytes);
jsonToken.Header.Remove("nonce");
jsonToken.Header.Add("nonce", hashedNonce);
header = tokenHandler.WriteToken(jsonToken).Split('.')[0];
accessToken = $"{header}.{payload}.{signature}";
context.Request.Headers["Authorization"] = $"Bearer {accessToken}";
}
}
await _next(context);
}
private string Encode(byte[] input)
{
var output = Convert.ToBase64String(input);
output = output.Split('=')[0]; // Remove any trailing '='s
output = output.Replace('+', '-'); // 62nd char of encoding
output = output.Replace('/', '_'); // 63rd char of encoding
return output;
}
}
}
这里是Auth的配置:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi((options) =>
{
options.Audience = "00000003-0000-0000-c000-000000000000";
},
(options) =>
{
options.ClientId = "your app registration client id";
options.TenantId = "your subscription tenant id";
options.Instance = "https://login.microsoftonline.com/";
options.Domain = "the domain of the tenant";
},
JwtBearerDefaults.AuthenticationScheme);
编码愉快!
我有一个源自 Identity Platform 示例的 SPA 应用程序,该示例最初调用图形 API。
我已将端点更改为调用本地 API。
SPA 使用 Azure AD 进行身份验证。
API 示例源自 API 的 VS 2019 项目模板。
、NET 4.7.2 - 没有 .NET Core。
我可以进行身份验证,并且在进行网络跟踪时 ID 和访问令牌都存在。
然而,在API这边我得到一个错误:
"IDX10511: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.X509SecurityKey, KeyId: '1E50B4475DAC931359D564309A3385FFAB7FB431', InternalId: 'f61f7746-3cff-4557-8b2c-b47fad9cf1e3'. , KeyId: 1E50B4475DAC931359D564309A3385FFAB7FB431"
解码访问令牌显示:
"{
"typ": "JWT",
"nonce": "G0Q6_BuYJUfZaBnX-l1Ox1eoncxXRT4KMThFBcn1-VA",
"alg": "RS256",
"x5t": "HlC0R12skxNZ1WQwmjOF_6t_tDE",
"kid": "HlC0R12skxNZ1WQwmjOF_6t_tDE"
}"
谷歌搜索,似乎签名失败是因为 header 中的随机数,这需要 "special processing".
所有验证都由 OWIN 完成。
知道这是什么或如何解决这个问题吗?
我认为这不是配置问题,因为我从未见过任何指定签名的配置。
所以我开始浏览 msal.js - 它是开源的。
"User.Read"(在我使用的示例中定义的范围)在许多地方被硬编码,所以我从示例中删除了这个范围并创建了一个名为 "abc".[=12 的虚拟范围=]
我还针对范围更改重新配置了 Azure AD。
瞧,一切正常。
更有趣的是,header是不同的:
{
"typ": "JWT",
"alg": "RS256",
"x5t": "HlC0R12skxNZ1WQwmjOF_6t_tDE",
"kid": "HlC0R12skxNZ1WQwmjOF_6t_tDE"
}
注意没有随机数。
所以我怀疑因为原始样本使用了 Microsoft Graph,"User.Read" 暗示了一些特殊的图形处理,添加了搞砸签名的随机数。
对于reference。
如果您仍然需要 User.Read 作用域,您可以通过添加一个在身份验证之前散列 nonce 的中间件来获得成功的签名验证
app.UseMiddleware<HashNonceJwtHeaderMiddleware>();
这里是中间件:
using System.IdentityModel.Tokens.Jwt;
using System.Security.Cryptography;
namespace MyApplication.Api.Infrastructure
{
public class HashNonceJwtHeaderMiddleware
{
private readonly RequestDelegate _next;
private static bool _hashNonceBeforeValidateToken = true;
public HashNonceJwtHeaderMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
string accessToken = context.Request.Headers["Authorization"].FirstOrDefault();
if (string.IsNullOrWhiteSpace(accessToken)) { return; }
accessToken = accessToken.Substring("Bearer ".Length);
var tokenHandler = new JwtSecurityTokenHandler();
var jsonToken = tokenHandler.ReadJwtToken(accessToken);
string[] parts = accessToken.Split('.');
string header = parts[0];
string payload = parts[1];
string signature = parts[2];
if (_hashNonceBeforeValidateToken &&
jsonToken.Header.TryGetValue("nonce", out object nonceAsObject))
{
string plainNonce = nonceAsObject.ToString();
using (SHA256 sha256 = SHA256.Create())
{
byte[] hashedNonceAsBytes = sha256.ComputeHash(
System.Text.Encoding.UTF8.GetBytes(plainNonce));
string hashedNonce = Encode(hashedNonceAsBytes);
jsonToken.Header.Remove("nonce");
jsonToken.Header.Add("nonce", hashedNonce);
header = tokenHandler.WriteToken(jsonToken).Split('.')[0];
accessToken = $"{header}.{payload}.{signature}";
context.Request.Headers["Authorization"] = $"Bearer {accessToken}";
}
}
await _next(context);
}
private string Encode(byte[] input)
{
var output = Convert.ToBase64String(input);
output = output.Split('=')[0]; // Remove any trailing '='s
output = output.Replace('+', '-'); // 62nd char of encoding
output = output.Replace('/', '_'); // 63rd char of encoding
return output;
}
}
}
这里是Auth的配置:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi((options) =>
{
options.Audience = "00000003-0000-0000-c000-000000000000";
},
(options) =>
{
options.ClientId = "your app registration client id";
options.TenantId = "your subscription tenant id";
options.Instance = "https://login.microsoftonline.com/";
options.Domain = "the domain of the tenant";
},
JwtBearerDefaults.AuthenticationScheme);
编码愉快!