【问题标题】:IDX10501: Signature validation failed. Unable to match keyIDX10501:签名验证失败。无法匹配密钥
【发布时间】:2020-07-15 07:44:07
【问题描述】:

我的任务是使用来自外部应用程序的 ADFS 令牌对 API 进行身份验证,因此我创建了两个应用程序,一个是 MVC 应用程序,比如说 A,它使用 SSO 凭据进行身份验证,另一个是是 WEB API 应用程序让我们说 B,所以在这里从 A,我正在使用 A 的 ADFS 令牌调用 B 的 API,但是,我得到了错误。有人帮我解决这个问题吗?

下面是应用B

中WEB API中的代码
           ConfigurationManager<OpenIdConnectConfiguration> configManager =
                new ConfigurationManager<OpenIdConnectConfiguration>(openIdConfig, new 
                                                                     OpenIdConnectConfigurationRetriever());

            OpenIdConnectConfiguration config = 
            configManager.GetConfigurationAsync().GetAwaiter().GetResult();
            result.EmailId = Claims.FirstOrDefault(claim => claim.Type == "upn").Value;
            result.WindowsNTId = Claims.FirstOrDefault(claim => claim.Type == "unique_name").Value;
            var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
            result.TokenCreatedOn = utc0.AddSeconds(Convert.ToInt64((Claims.FirstOrDefault(claim => 
            claim.Type == "iat").Value)));
            result.TokenExpiresOn = utc0.AddSeconds(Convert.ToInt64((Claims.FirstOrDefault(claim => 
            claim.Type == "exp").Value)));

            // Use System.IdentityModel.Tokens.Jwt library to validate the token
            JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();

            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                ValidateIssuer = true,
                ValidIssuer = config.Issuer,
                IssuerSigningKeys = config.SigningKeys,
                ValidateAudience = true,
                ValidAudience = expectedAudience
            };

            SecurityToken validatedToken;

            try
            {
                var claimsPrincipal = tokenHandler.ValidateToken(RawData, tokenValidationParameters, 
                out validatedToken);

            }
            catch (Exception ex)
            {

            }

以下是异常消息。

    IDX10501: Signature validation failed. Unable to match key: 
    kid: 'System.String'.
    Exceptions caught:System.Text.StringBuilder'. 
    token: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'.  

【问题讨论】:

    标签: oauth-2.0 jwt azure-active-directory openid-connect adfs


    【解决方案1】:

    当解码的密钥 (kid) 不是有效密钥时会发生这种情况(可能是旧密钥,因为证书密钥通常会更改)。

    来自https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.cs

    if (kidExists)
    {
         if (kidMatched)
         throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidSignatureException(LogHelper.FormatInvariant(TokenLogMessages.IDX10511, keysAttempted, jwtToken.Kid, exceptionStrings, jwtToken)));
    
         throw LogHelper.LogExceptionMessage(new SecurityTokenSignatureKeyNotFoundException(LogHelper.FormatInvariant(TokenLogMessages.IDX10501, jwtToken.Kid, exceptionStrings, jwtToken)));
    }
    

    在我的情况下,问题的原因是密钥模数中存在空的第一个字节。解决方案是删除第一个空字节。

    https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/1122

    var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(configFileUrl, new OpenIdConnectConfigurationRetriever());
    var openIdConfig = configManager.GetConfigurationAsync().Result; #region workaround for "Error validating identity token : IDX10511"
    //The issue you are facing is caused by the null first byte.
    //This is contrary to the JWA (https://tools.ietf.org/html/rfc7518#section-6.3.1.1).
    //.NET Core will account for the null byte and .NET framework, apparently, won't.
    List<SecurityKey> keys = new List<SecurityKey>();
    foreach (var key in openIdConfig.SigningKeys)
    {
         if (key.CryptoProviderFactory.IsSupportedAlgorithm("SHA256"))
         {
              var modulus = ((RsaSecurityKey)key).Parameters.Modulus;
              var exponent = ((RsaSecurityKey)key).Parameters.Exponent;
    
              if (modulus.Length == 257 && modulus[0] == 0)
              {
                   var newModulus = new byte[256];
                   Array.Copy(modulus, 1, newModulus, 0, 256);
                   modulus = newModulus;
              }
              RSAParameters rsaParams = new RSAParameters();
              rsaParams.Modulus = modulus;
              rsaParams.Exponent = exponent;
    
              keys.Add(new RsaSecurityKey(rsaParams));
         }
         else
         {
              keys.Add(key);
         }
    }
    #endregion
    
    TokenValidationParameters validationParameters =
    new TokenValidationParameters
    {
         // Validate the JWT Issuer (iss) claim
         ValidateIssuer = true,
         ValidIssuer = issuer,
    
         //// Validate the JWT Audience (aud) claim
         ValidateAudience = true,
         ValidAudience = audience,
    
         ValidateIssuerSigningKey = true,
         IssuerSigningKeys = keys,
    
         RequireExpirationTime = true,
         ValidateLifetime = true,
         RequireSignedTokens = true,
    };
    
    // Now validate the token. If the token is not valid for any reason, an exception will be thrown by the method
    SecurityToken validatedToken;
    JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
    
    var claimsPrincipal = handler.ValidateToken(idToken, validationParameters, out validatedToken);
    

    【讨论】:

    • 我编辑了我的答案,我猜它不完整,你能删除反对票吗?
    猜你喜欢
    • 2020-03-10
    • 2017-12-31
    • 2023-03-06
    • 2020-02-24
    • 2020-12-28
    • 2020-11-14
    • 2018-07-23
    • 2018-02-19
    • 2017-09-02
    相关资源
    最近更新 更多