我正在尝试构建一种验证我的令牌的方法。我正在使用 Open Id Connect 授权代码流从 Azure Active Directory 检索我的令牌。我获得的令牌是 access_token 和 id_token。我正在使用 .NET Core。
我的验证码如下:
string stsDiscoveryEndpoint = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
var handler = new JwtSecurityTokenHandler();
ConfigurationManager<OpenIdConnectConfiguration> configManager = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());
OpenIdConnectConfiguration config = configManager.GetConfigurationAsync().Result;
try
{
TokenValidationParameters validationParameters = new TokenValidationParameters
{
ValidIssuers = new [] { "https://login.microsoftonline.com/tenantid/v2.0" },
ValidAudiences = new [] { "client-Id" },
ValidateAudience = true,
ValidateIssuer = true,
IssuerSigningKeys = config.SigningKeys,
ValidateLifetime = true
};
var tokenHandler = new JwtSecurityTokenHandler();
SecurityToken validatedToken = null;
tokenHandler.ValidateToken(token.AccessToken, validationParameters, out validatedToken);
return validatedToken != null;
}
catch (SecurityTokenInvalidSignatureException ex)
{
return false;
}
catch(SecurityTokenValidationException)
{
return false;
}
下面的代码适用于id_token但是 对于 access_token 不起作用
对 access_token 执行此方法时收到的错误消息是:
IDX10511:签名验证失败。尝试过的密钥: 'Microsoft.IdentityModel.Tokens.X509SecurityKey ,KeyId:CtAAALb-8NsDe333734859crfOc '。 孩子:“CtAAALb-8NsDe333734859crfOc”。 捕获的异常: ' '
这是一个代码示例,您可以在其中看到
jsonToken.Header.Add("nonce", hashedNonce);
private static bool _hashNonceBeforeValidateToken = true;
private const string MicrosoftGraphApplicationId = "00000003-0000-0000-c000-000000000000";
private const string MicrosoftIssuer = "https://sts.windows.net";
public static bool ValidateTokenSignature(string accessToken, ApplicationConfiguration applicationConfiguration) {
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];
//hash nonce and update header with the hash before validating
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 = Base64Url.Encode(hashedNonceAsBytes);
jsonToken.Header.Remove("nonce");
jsonToken.Header.Add("nonce", hashedNonce);
header = tokenHandler.WriteToken(jsonToken).Split('.')[0];
accessToken = $"{header}.{payload}.{signature}";
}
}
//get the Microsoft JWT signature public key
string stsDiscoveryEndpoint = $"https://login.microsoftonline.com/{applicationConfiguration.TenantId}/v2.0/.well-known/openid-configuration";
if (jsonToken.Header.TryGetValue("ver", out object version) && version.ToString() == "1.0")
{
stsDiscoveryEndpoint = $"https://login.microsoftonline.com/{applicationConfiguration.TenantId}/.well-known/openid-configuration";
}
var openidConfigManaged = new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint,
new OpenIdConnectConfigurationRetriever(),
new HttpDocumentRetriever());
var configTask = openidConfigManaged.GetConfigurationAsync();
configTask.Wait();
var config = configTask.Result;
var parameteres = new TokenValidationParameters()
{
RequireAudience = true,
ValidateAudience = true,
ValidAudiences = new[] { applicationConfiguration.ApplicationId, MicrosoftGraphApplicationId },
ValidateIssuer = true,
ValidIssuers = new string[] { $"{MicrosoftIssuer}/{applicationConfiguration.TenantId}/", config.Issuer },
IssuerSigningKeys = config.SigningKeys,
ValidateIssuerSigningKey = true,
RequireExpirationTime = true,
ValidateLifetime = true,
};
var claimPrincipal = tokenHandler.ValidateToken(
accessToken, parameteres, out SecurityToken validatedToken);
return claimPrincipal.Identity.IsAuthenticated;
}
access_token
受众是您的 API 或 Microsoft Graph/其他第 3 方服务吗?只有验证“你”(你的服务)消耗的代币才有意义,其他受众将自行处理此问题。最重要的是,该 JWT 的签名对您来说可能是不透明的。请参阅此了解更多信息 - https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/812#issuecomment-456700813当您不创建自定义范围时,就会发生这种情况。在这种情况下,MSAL 生成标头中具有“nonce”的 JWT。此类 JWT 无法通过您的 .net 代码轻松验证。但是,如果您确实创建了自定义范围(如此处