Asp.net web api JwtAuthForWebAPI中的SignatureRefercationFailedException

Asp.net web api JwtAuthForWebAPI中的SignatureRefercationFailedException,asp.net-web-api,asp.net-identity,access-token,jwt,json-web-token,Asp.net Web Api,Asp.net Identity,Access Token,Jwt,Json Web Token,我已经连接了nuget项目,但是我无法验证生成的令牌。我最终得到了500个错误。我在生成令牌和配置JwtAuthenticationMessageHandler时使用完全相同的键值 这是生成令牌的代码: var tokenHandler = new JwtSecurityTokenHandler(); var symmetricKey = JsonWebTokenSecretKey.GetBytes(); var now = DateTime.UtcNow; var tokenDescript

我已经连接了nuget项目,但是我无法验证生成的令牌。我最终得到了500个错误。我在生成令牌和配置JwtAuthenticationMessageHandler时使用完全相同的键值

这是生成令牌的代码:

var tokenHandler = new JwtSecurityTokenHandler();
var symmetricKey = JsonWebTokenSecretKey.GetBytes();
var now = DateTime.UtcNow;

var tokenDescriptor = new SecurityTokenDescriptor
{
    Subject = new ClaimsIdentity(
        new[]{
            new Claim(JwtClaimKeys.Audience, SessionManager.Current.ApplicationId.ToString()), 
            new Claim(JwtClaimKeys.Subject, userLoginRequest.ApplicationInstanceId.ToString())
        }),
    TokenIssuerName = "My Company",
    Lifetime = new Lifetime(now, now.AddMinutes(tokenLifetimeInMinutes)),
    SigningCredentials = new SigningCredentials(
        new InMemorySymmetricSecurityKey(symmetricKey),
        "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256",
        "http://www.w3.org/2001/04/xmlenc#sha256")
};

tokenDescriptor.Subject.AddClaims(GetRoles(userLoginRequest));

var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
这是注册身份验证处理程序的代码:

var keyBuilder = new SecurityTokenBuilder();

var jwtHandler = new JwtAuthenticationMessageHandler
{
    Issuer = "My Company",
    AllowedAudience = ApplicationId.ToString(),
    SigningToken = keyBuilder.CreateFromKey(JsonWebTokenSecretKey),
    PrincipalTransformer = new MyUserPrincipleTransformer()
};

config.MessageHandlers.Add(jwtHandler);
这是我得到的错误:

{"Message":"An error has occurred.","ExceptionMessage":"IDX10503: Signature validation failed. Keys tried: 'System.IdentityModel.Tokens.InMemorySymmetricSecurityKey\r\n'.\nExceptions caught:\n ''.\ntoken: '{\"typ\":\"JWT\",\"alg\":\"HS256\"}.{\"aud\":\"1\",\"sub\":\"3\",\"role\":[\"User\",\"Admin\"],\"iss\":\"My Company\",\"exp\":1429547369,\"nbf\":1429543769}'","ExceptionType":"System.IdentityModel.SignatureVerificationFailedException",
"StackTrace":"   
at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters)\r\n   
at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateToken(String securityToken, TokenValidationParameters validationParameters, SecurityToken& validatedToken)\r\n   
at JwtAuthForWebAPI.JwtSecurityTokenHandlerAdapter.ValidateToken(IJwtSecurityToken securityToken, TokenValidationParameters validationParameters)\r\n   
at JwtAuthForWebAPI.JwtAuthenticationMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   
at System.Web.Http.HttpServer.<SendAsync>d__0.MoveNext()"}
有趣的是,我可以使用我的密钥验证令牌。我怀疑这可能与JwtAuthForWebAPI库在查看与系统不同的内容有关。JWT库生成的标识?

这是Jamie(JwtAuthForWebAPI包的作者)。服务器配置代码(具体来说,
SecurityTokenBuilder.CreateFromKey(string)
-假定给定的字符串是base64编码的。或者需要假设或参数来指示转换为字节数组所使用的编码。我选择假设字符串是base64编码的。我相信有一种更清晰的方法可以将字符串键转换为SecurityToken,但这就是今天的代码

在JwtAuthForWebAPI.SampleClient项目中,您可以看到我使用了
Convert.FromBase64String()
方法,而不是从
编码
类使用
GetBytes()
方法:

public const string SymmetricKey = "YQBiAGMAZABlAGYAZwBoAGkAagBrAGwAbQBuAG8AcABxAHIAcwB0AHUAdgB3AHgAeQB6ADAAMQAyADMANAA1AA==";

// ...

var key = Convert.FromBase64String(SymmetricKey);
var credentials = new SigningCredentials(
    new InMemorySymmetricSecurityKey(key),
    "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256",
    "http://www.w3.org/2001/04/xmlenc#sha256");
您可以继续使用当前的令牌生成代码,但在服务器上

请尝试在服务器配置代码中指定JsonWebTokenSecretKey的base64编码版本。您可以使用类似的站点对其进行编码,或者尝试以下代码:

var base64key = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonWebTokenSecretKey));

var keyBuilder = new SecurityTokenBuilder();
var jwtHandler = new JwtAuthenticationMessageHandler
{
    Issuer = "My Company",
    AllowedAudience = ApplicationId.ToString(),
    SigningToken = keyBuilder.CreateFromKey(base64key),
    PrincipalTransformer = new MyUserPrincipleTransformer()
};
让我知道这是否有效

此外,我将更新库以捕获SignatureReferationFailedException异常并返回401,而不是让内部服务器错误发生。您仍然需要将密钥指定为base64字符串,但至少这样的配置问题不会导致500错误


同样,请让我知道这是否奏效。

这只是我基于@Jamie answer的代码示例

 protected string GetUsername(string token)
        {
            string secret = "keyyyyy!@3";
           var key = Convert.FromBase64String(secret);

            var IssuerSigningKey = new SymmetricSecurityKey(key);
            IdentityModelEventSource.ShowPII = true;
            var SigningCredentials = new SigningCredentials(
                     IssuerSigningKey,
                     SecurityAlgorithms.HmacSha256Signature);

            var handler = new JwtSecurityTokenHandler();
            var tokenSecure = handler.ReadToken(token) as SecurityToken;
            var validations = new TokenValidationParameters
            {

                ValidateIssuerSigningKey = true,
                IssuerSigningKey = IssuerSigningKey,
                ValidateIssuer = false,
                ValidateAudience = false
            };
            var claims = handler.ValidateToken(token, validations, out tokenSecure);
            return claims.Identity.Name;
        }

非常感谢你!在创建令牌的过程中,我将其更改为使用以下行:var symmetricKey=Convert.FromBase64String(base64Key);Jamie-我只在生产上面临同样的问题,它在我的开发环境中工作得很好。请注意,我没有在任何环境中使用certificatesubject/certificate。此外,开发人员网站有“http”协议,产品有“https”协议,但web Api没有使用证书。令牌的过期期限为30天,但在大约30分钟内过期,有没有深入研究此问题的建议?@gaurav上述问题(来自Adam Fisher)已通过确保对称密钥作为base64编码字符串提供给库来解决。你试过了吗?如果不使用证书,您现在如何对令牌进行签名?@Jamie-现在,令牌工作正常。我遇到了另一个问题,象征生命是30天。这很奇怪,但一旦客户端重新启动他/她的机器,相同的令牌(之前验证过)就失效了。有趣的是,我可以使用我的密钥验证令牌,使用任何建议吗?@Jamie:当我尝试验证过期令牌时,我得到的是内部服务器错误,而不是401。我正在使用asp.net core 1。例如:新的JwtSecurityTokenHandler().ValidateToken(我的过期令牌)
 protected string GetUsername(string token)
        {
            string secret = "keyyyyy!@3";
           var key = Convert.FromBase64String(secret);

            var IssuerSigningKey = new SymmetricSecurityKey(key);
            IdentityModelEventSource.ShowPII = true;
            var SigningCredentials = new SigningCredentials(
                     IssuerSigningKey,
                     SecurityAlgorithms.HmacSha256Signature);

            var handler = new JwtSecurityTokenHandler();
            var tokenSecure = handler.ReadToken(token) as SecurityToken;
            var validations = new TokenValidationParameters
            {

                ValidateIssuerSigningKey = true,
                IssuerSigningKey = IssuerSigningKey,
                ValidateIssuer = false,
                ValidateAudience = false
            };
            var claims = handler.ValidateToken(token, validations, out tokenSecure);
            return claims.Identity.Name;
        }