在我的客户端(nextAuth),我从 Microsoft 获得了一次访问令牌,现在我希望从 ASP.NET Core Web API 上的后端验证该令牌。据我所知,该过程是从 Microsoft 获取密钥,并且具有相同“孩子”的密钥使用该密钥进行验证。
这是我从 Microsoft 获得的 JWT 的标头部分:
{
"nonce": "v9eWI-Nv75YgvN8IgSNSlHPK-UH8iOcEUz8KXqj6DeA",
"alg": "RS256",
"x5t": "H9nj5AOSswMphg1SFx7jaV-lB9w",
"kid": "H9nj5AOSswMphg1SFx7jaV-lB9w"
}
现在,经过大量尝试,我被迫对从 Microsoft 获得的密钥的证书值进行硬编码以获得一些成功
我访问了 URL https://login.microsoftonline.com/{myTenantId}/discovery/keys?appid={clientId}
得到了这个
{
"kty": "RSA",
"use": "sig",
"kid": "H9nj5AOSswMphg1SFx7jaV-lB9w",
"x5t": "H9nj5AOSswMphg1SFx7jaV-lB9w",
"n": "iheTlbqieo0KzaFBTz6dxt9LAENfe2d0ywnpvZx9khzurtApc4ThWBpeoTBI6UpReeCwyW6DQjJSGCqHwe-wqRdgoiMc0PV-danrh0px38x2KL_j7VoHR0hlQBYOpp5GBMdz-Nsc80wBtHAqxz7Nno3qYNTXUvwZ2LSbbvgoPXrh0zhLlSrn2gAroRv6Z8xSOVg3CSmZeVgZHJv4aMYQiBiIIZW68YN5ywHxOf6-LdrhqN24NPSLYUNPKGxCkUkWg-VV-iulUqIkDxn3SKiX4zVA-jevbuUrsK3MeRHoJLqXMf8KnpPkf4ZLCTLdUNFyLyxFvqnm6QUAgpDrQ_rxhw",
"e": "AQAB",
"x5c": [
"MIIC/jCCAeagAwIBAgIJAJjMBdn72zEjMA0GCSqGSIb3DQEBCwUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMjQwODE4MTkzMzIzWhcNMjkwODE4MTkzMzIzWjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiheTlbqieo0KzaFBTz6dxt9LAENfe2d0ywnpvZx9khzurtApc4ThWBpeoTBI6UpReeCwyW6DQjJSGCqHwe+wqRdgoiMc0PV+danrh0px38x2KL/j7VoHR0hlQBYOpp5GBMdz+Nsc80wBtHAqxz7Nno3qYNTXUvwZ2LSbbvgoPXrh0zhLlSrn2gAroRv6Z8xSOVg3CSmZeVgZHJv4aMYQiBiIIZW68YN5ywHxOf6+LdrhqN24NPSLYUNPKGxCkUkWg+VV+iulUqIkDxn3SKiX4zVA+jevbuUrsK3MeRHoJLqXMf8KnpPkf4ZLCTLdUNFyLyxFvqnm6QUAgpDrQ/rxhwIDAQABoyEwHzAdBgNVHQ4EFgQUVOgUL8kBykezhhopW+Whb6mtqhowDQYJKoZIhvcNAQELBQADggEBAHqgxwjA+D7HzUT5mNRf8uizC9SkHdLXULyZTehFbSYEB3SYXZIbUWJcd88uaDUZ7CxPaojg6swmuB9XnzcZh8Gpa5y1ThSWvmPvUIDq1e03OJzhsC6dPmwoysmLvovngkGJ/AWURK7zRot53DLYWt0d/0KPDExPsovava0LeQjU8bLxHwQ9+8JFFxoN/aE85TQc8Whw+xZ4NX6BdTiucY8ku0smJLblwWui+mGyFSfDFW9r/r8LMUifgXTkaLYz4Z7sQdPFsdSoAR2jOzKhiz6acyQ1R4QUheN0EBmuPSsbu9M+E6tSYD+4q3GmQWtXjVagJoKPos0DIhe785YZjtI="
]
}
正如你所看到的,两者都有相同的
kid
。
这是我的后端代码:
private const string KeyString = @"MIIC/jCCAeagAwIBAgIJAJjMBdn72zEjMA0GCSqGSIb3DQEBCwUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMjQwODE4MTkzMzIzWhcNMjkwODE4MTkzMzIzWjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiheTlbqieo0KzaFBTz6dxt9LAENfe2d0ywnpvZx9khzurtApc4ThWBpeoTBI6UpReeCwyW6DQjJSGCqHwe+wqRdgoiMc0PV+danrh0px38x2KL/j7VoHR0hlQBYOpp5GBMdz+Nsc80wBtHAqxz7Nno3qYNTXUvwZ2LSbbvgoPXrh0zhLlSrn2gAroRv6Z8xSOVg3CSmZeVgZHJv4aMYQiBiIIZW68YN5ywHxOf6+LdrhqN24NPSLYUNPKGxCkUkWg+VV+iulUqIkDxn3SKiX4zVA+jevbuUrsK3MeRHoJLqXMf8KnpPkf4ZLCTLdUNFyLyxFvqnm6QUAgpDrQ/rxhwIDAQABoyEwHzAdBgNVHQ4EFgQUVOgUL8kBykezhhopW+Whb6mtqhowDQYJKoZIhvcNAQELBQADggEBAHqgxwjA+D7HzUT5mNRf8uizC9SkHdLXULyZTehFbSYEB3SYXZIbUWJcd88uaDUZ7CxPaojg6swmuB9XnzcZh8Gpa5y1ThSWvmPvUIDq1e03OJzhsC6dPmwoysmLvovngkGJ/AWURK7zRot53DLYWt0d/0KPDExPsovava0LeQjU8bLxHwQ9+8JFFxoN/aE85TQc8Whw+xZ4NX6BdTiucY8ku0smJLblwWui+mGyFSfDFW9r/r8LMUifgXTkaLYz4Z7sQdPFsdSoAR2jOzKhiz6acyQ1R4QUheN0EBmuPSsbu9M+E6tSYD+4q3GmQWtXjVagJoKPos0DIhe785YZjtI=";
[HttpPost("validate-token3")]
public IActionResult DecodeValidToken()
{
try
{
string accessToken = "MyTokenHereWhichICannotPasteHere";
var certificate = new X509Certificate2(Convert.FromBase64String(KeyString));
var rsa = certificate.GetRSAPublicKey();
var rsaSecurityKey = new RsaSecurityKey(rsa);
var tokenHandler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = rsaSecurityKey,
ValidateIssuer = false,
ValidateAudience = false
};
var principal = tokenHandler.ValidateToken(accessToken, validationParameters, out SecurityToken validatedToken);
return Ok(principal.Claims);
}
catch (SecurityTokenInvalidSignatureException ex)
{
return Unauthorized(new { Message = "Invalid token signature", Details = ex.Message });
}
catch (Exception ex)
{
return StatusCode(500, new { Message = "Internal server error", Details = ex.Message });
}
}
即使我的令牌有
kid
,我仍然收到此错误:
Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException:'IDX10503:签名验证失败。托肯没有孩子。尝试过的密钥:“Microsoft.IdentityModel.Tokens.RsaSecurityKey,KeyId:”,InternalId:“y16ADo8cPNxOAHfa262kqg7euKagSoVzzY5Wo4CzT5c”。 , 密钥 ID: '。 TokenValidationParameters 中的键数:“1”。 配置中的键数:“0”。 捕获异常:
”。
令牌:'[类型为“System.IdentityModel.Tokens.Jwt.JwtSecurityToken”的安全工件已隐藏。有关更多详细信息,请参阅 https://aka.ms/IdentityModel/SecurityArtifactLogging。]'。有关详细信息,请参阅 https://aka.ms/IDX10503。'
过去 4 天我一直在尝试解决这个问题,但仍然没有运气,即使我尝试了一种不同的方法,我们从 Microsoft 获取密钥并传递所有密钥进行验证
我生成了访问令牌并尝试使用与下面相同的代码来验证令牌:
遇到了同样的错误:
注意:Microsoft Graph API 令牌并不需要验证。
因此要解决该错误,请检查以下内容:
公开 API 并添加范围:
授予API权限:
确保通过将 scope 传递为 api://***/ScopeName
来生成访问令牌
现在token有效并且成功得到输出:
class Program
{
private const string KeyString = @"xxx";
static void Main(string[] args)
{
string accessToken = "MyTokenHereWhichICannotPasteHere";
try
{
var certificate = new X509Certificate2(Convert.FromBase64String(KeyString));
var rsa = certificate.GetRSAPublicKey();
var rsaSecurityKey = new RsaSecurityKey(rsa);
var tokenHandler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = rsaSecurityKey,
ValidateIssuer = false,
ValidateAudience = false
};
var principal = tokenHandler.ValidateToken(accessToken, validationParameters, out SecurityToken validatedToken);
Console.WriteLine("Token is valid. Claims:");
foreach (var claim in principal.Claims)
{
Console.WriteLine($"{claim.Type}: {claim.Value}");
}
}
catch (SecurityTokenInvalidSignatureException ex)
{
Console.WriteLine($"Unauthorized: Invalid token signature. Details: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
请参阅此 GitHub 博客 Azure AD 身份验证、Next-Auth JWT 和 .NET Core Web API · nextauthjs/next-auth · 讨论 #5996 · GitHub,其中访问令牌是使用 Next-Auth 在前端生成的。