c# - OAuth 不记名 token 身份验证未通过签名验证

标签 c# asp.net security oauth jwt

我在 token 使用者上收到以下错误。解决此问题的任何帮助将不胜感激。谢谢。


"IDX10503: Signature validation failed.

Keys tried: 'System.IdentityModel.Tokens.SymmetricSecurityKey '. Exceptions caught: 'System.InvalidOperationException: IDX10636: SignatureProviderFactory.CreateForVerifying returned null for key: 'System.IdentityModel.Tokens.SymmetricSecurityKey', signatureAlgorithm: 'http://www.w3.org/2001/04/xmldsig-more#hmac-sha256'. at Microsoft.IdentityModel.Logging.LogHelper.Throw(String message, Type exceptionType, EventLevel logLevel, Exception innerException) at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateSignature(Byte[] encodedBytes, Byte[] signature, SecurityKey key, String algorithm) at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters) '. token: 'token info was here'"

OAuth 服务器上的 token 生成代码

 using (var ctlr = new EntityController())
        {
            var authRepo = ctlr.GetAuthModelRepository();

            string clientId;

            ticket.Properties.Dictionary.TryGetValue(WebConstants.OwinContextProps.OAuthClientIdPropertyKey, out clientId);

            if (string.IsNullOrWhiteSpace(clientId))
            {
                throw new InvalidOperationException("AuthenticationTicket.Properties does not include audience");
            }


            //audience record
            var client = authRepo.FindAuthClientByOAuthClientID(clientId);

            var issued = ticket.Properties.IssuedUtc;
            var expires = ticket.Properties.ExpiresUtc;


            var hmac = new HMACSHA256(Convert.FromBase64String(client.Secret));
            var signingCredentials = new SigningCredentials(
                new InMemorySymmetricSecurityKey(hmac.Key),
                Algorithms.HmacSha256Signature, Algorithms.Sha256Digest);

            TokenValidationParameters validationParams =
                new TokenValidationParameters()
                {
                    ValidAudience = clientId,
                    ValidIssuer = _issuer,
                    ValidateLifetime = true,
                    ValidateAudience = true,
                    ValidateIssuer = true,
                    RequireSignedTokens = true,
                    RequireExpirationTime = true,
                    ValidateIssuerSigningKey = true,
                    IssuerSigningToken = new BinarySecretSecurityToken(hmac.Key)
                };

            var jwtHandler = new JwtSecurityTokenHandler();

            var jwt = new JwtSecurityToken(_issuer, clientId, ticket.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingCredentials);

            jwtOnTheWire = jwtHandler.WriteToken(jwt);

            SecurityToken validatedToken = null;
            jwtHandler.ValidateToken(jwtOnTheWire, validationParams,out validatedToken);
            if (validatedToken == null)
                return "token_validation_failed";

        }
        return jwtOnTheWire;

Owin Startup.cs 中的 token 消耗\验证 ASP.Net 5 vNext 站点

public void ConfigureServices(IServiceCollection 服务)

services.ConfigureOAuthBearerAuthentication(config =>
        {

            //oauth validation
            var clientSecret = "not the real secret";

            var hmac = new HMACSHA256(Convert.FromBase64String(clientSecret));
            var signingCredentials = new SigningCredentials(
                new SymmetricSecurityKey(hmac.Key), Algorithms.HmacSha256Signature, Algorithms.Sha256Digest);

            config.TokenValidationParameters.ValidAudience = "myappname";
            config.TokenValidationParameters.ValidIssuer = "mydomain.com";
            config.TokenValidationParameters.RequireSignedTokens = true;
            config.TokenValidationParameters.RequireExpirationTime = true;
            config.TokenValidationParameters.ValidateLifetime = true;
            config.TokenValidationParameters.ValidateIssuerSigningKey = true;
            config.TokenValidationParameters.ValidateSignature = true;
            config.TokenValidationParameters.ValidateAudience = true;
            config.TokenValidationParameters.IssuerSigningKey = signingCredentials.SigningKey;
        });

public void Configure(IApplicationBuilder app)

app.UseOAuthBearerAuthentication(config =>
            {

                config.AuthenticationScheme = "Bearer";
                config.AutomaticAuthentication = true;
            });

最佳答案

我能够将自己的签名验证添加到 TokenValidationParameters 然后我将 JWT 的传入原始签名与此代码中的编译签名进行比较,如果匹配则签名有效。

我不明白为什么使用内置签名验证没有发生这种情况,这可能是 vNext Identity token 框架 beta 6 中的一个可能错误。

public void ConfigureServices(IServiceCollection 服务)

config.TokenValidationParameters.SignatureValidator =
                delegate (string token, TokenValidationParameters parameters)
                {
                    var clientSecret = "not the real secret";

                    var jwt = new JwtSecurityToken(token);

                    var hmac = new HMACSHA256(Convert.FromBase64String(clientSecret));

                    var signingCredentials = new SigningCredentials(
                       new SymmetricSecurityKey(hmac.Key), SecurityAlgorithms.HmacSha256Signature, SecurityAlgorithms.Sha256Digest);

                    var signKey = signingCredentials.SigningKey as SymmetricSecurityKey;


                    var encodedData = jwt.EncodedHeader + "." + jwt.EncodedPayload;
                    var compiledSignature = Encode(encodedData, signKey.Key);

                    //Validate the incoming jwt signature against the header and payload of the token
                    if (compiledSignature != jwt.RawSignature)
                    {
                        throw new Exception("Token signature validation failed.");
                    }

                    return jwt;
                };

编码辅助方法

 public string Encode(string input, byte[] key)
        {
            HMACSHA256 myhmacsha = new HMACSHA256(key);
            byte[] byteArray = Encoding.UTF8.GetBytes(input);
            MemoryStream stream = new MemoryStream(byteArray);
            byte[] hashValue = myhmacsha.ComputeHash(stream);
            return Base64UrlEncoder.Encode(hashValue);
        }

关于c# - OAuth 不记名 token 身份验证未通过签名验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31948426/

相关文章:

c# - 抛出负数组大小的 OverflowException 背后的基本原理?

c# - JSON.NET DataContractJsonSerializer 和 Newtonsoft JSON 序列化程序有什么区别

security - 如何向一组用户授予对所有 TFS 团队项目的只读访问权限?

java - 如何使用权限保护rest api

c# - 内部元素数量不变的 LINQ.SelectMany 的替代品

c# - 以编程方式测试 SQL Server 连接的最佳方法是什么?

c# - 附加类型为 'X' 的实体失败,因为同一类型的另一个实体

c# - 您好,我正在尝试在 Azure 应用程序服务中运行 Web 作业,但它抛出与日期时间相关的错误

ASP.NET 我无法将数据传输到另一个页面

html - SSL 网站,但有警告