3
votes

I get the following error on the token consumer. Any help resolving this will be most appreciated. Thanks.


"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'"

Token Generation Code on OAuth server

 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;

Token Consumption\validation ASP.Net 5 vNext site within Owin Startup.cs

public void ConfigureServices(IServiceCollection services)

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;
            });
1

1 Answers

6
votes

I was able to add my own signature validation to the TokenValidationParameters Then I compared the incoming Raw signature of the JWT to the compiled signature in this code and if it matches the signature is valid.

Why this didn't happen using the builtin signature validation is beyond me, maybe it's a possible bug in beta 6 of the vNext Identity token framework.

public void ConfigureServices(IServiceCollection services)

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;
                };

Encode helper method

 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);
        }