IDX10503:签名验证失败 [英] IDX10503: Signature validation failed
问题描述
重新启动或发布应用程序后,我收到带有有效令牌的以下错误
I getting the following error with a valid token after the application re-start or publish
IDX10503: Signature validation failed. Keys tried: 'System.IdentityModel.Tokens.RsaSecurityKey
Exceptions caught:
token: '{"typ":"JWT","alg":"RS256","kid":null}.{"unique_name":"test@test.com","iss":"XXXXXX","aud":"XXXXX","exp":1444876186}'
这是生成KEY的功能
private void generateRsaKeys()
{
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(2048))
{
key = new RsaSecurityKey(rsa.ExportParameters(true));
credentials = new SigningCredentials (key,SecurityAlgorithms.RsaSha256Signature, SecurityAlgorithms.Sha256Digest);
rsa.PersistKeyInCsp = true;
}
}
这是完成配置的方式
services.ConfigureOAuthBearerAuthentication(options =>
{
options.AutomaticAuthentication = true;
options.TokenValidationParameters.IssuerSigningKey = generateRsaKeys();
options.TokenValidationParameters.ValidAudience = audience;
options.TokenValidationParameters.ValidIssuer = issuer;
});
app.UseStaticFiles();
app.UseOAuthBearerAuthentication();
// Add MVC to the request pipeline.
app.UseMvc();
这是我的控制器上的动作
and this is the action on my controller
// POST: /token
[HttpPost()]
public async Task<IActionResult> Token([FromBody] LoginModel model)
{
if (!ModelState.IsValid)
return HttpBadRequest();
JwtSecurityTokenHandler handler = _bearerOptions.SecurityTokenValidators.OfType<JwtSecurityTokenHandler>().First();
try
{
var user = await _Repo.GetDetailAsync(model.Email);
if (!model.Password.Equals(user.Password))
return HttpUnauthorized();
JwtSecurityToken securityToken = handler.CreateToken
(
issuer: _bearerOptions.TokenValidationParameters.ValidIssuer,
audience: _bearerOptions.TokenValidationParameters.ValidAudience,
signingCredentials: _signingCredentials,
subject: new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, user.Email) }),
expires: DateTime.Now.AddMinutes(2)
);
string token = handler.WriteToken(securityToken);
return new ObjectResult(new TokenModel() { AccessToken = token, TokenType = "bearer" });
}
catch (Exception ex)
{
// TODO: add loggin logic here
return HttpUnauthorized();
}
}
推荐答案
如果每次(重新)启动服务器时都在生成一个新的RSA密钥,那也就不足为奇了:无法验证使用KEY A
签名的令牌使用KEY B
.为了使方案正常工作,您需要将RSA密钥存储在某个位置,并在启动过程中使用相同的密钥.
If you're generating a new RSA key each time you (re)start your server, then it's not surprising: tokens signed with KEY A
cannot be validated using KEY B
. For your scenario to work, you need to store your RSA key somewhere and use the same one during startup.
一种方法是调用rsa.ExportParameters(true)
并将不同的参数存储在某处,因此您可以轻松地使用rsa.ImportParameters(...)
检索和导入它们.
One way is to call rsa.ExportParameters(true)
and store the different parameters somewhere, so you can easily retrieve and import them using rsa.ImportParameters(...)
.
但是最好的选择是使用AspNet.Security.OpenIdConnect.Server
,它将在最新版本中自动为您生成并存储RSA密钥:
But your best option is to use AspNet.Security.OpenIdConnect.Server
, that will automatically generate and store a RSA key for you in the last version:
public class Startup {
public void ConfigureServices(IServiceCollection services) {
services.AddAuthentication();
services.AddCaching();
}
public void Configure(IApplicationBuilder app) {
// Add a new middleware validating access tokens issued by the OIDC server.
app.UseJwtBearerAuthentication(options => {
options.AutomaticAuthentication = true;
options.Authority = "resource_server_1";
options.RequireHttpsMetadata = false;
});
// Add a new middleware issuing tokens.
app.UseOpenIdConnectServer(options => {
options.AllowInsecureHttp = true;
options.Provider = new OpenIdConnectServerProvider {
// Override OnValidateClientAuthentication to skip client authentication.
OnValidateClientAuthentication = context => {
// Call Skipped() since JS applications cannot keep their credentials secret.
context.Skipped();
return Task.FromResult<object>(null);
},
// Override OnGrantResourceOwnerCredentials to support grant_type=password.
OnGrantResourceOwnerCredentials = context => {
// Do your credentials validation here.
// Note: you can call Rejected() with a message
// to indicate that authentication failed.
var identity = new ClaimsIdentity(OpenIdConnectDefaults.AuthenticationScheme);
identity.AddClaim(ClaimTypes.NameIdentifier, "todo");
// By default, claims are not serialized in the access and identity tokens.
// Use the overload taking a "destination" to make sure your claims
// are correctly inserted in the appropriate tokens.
identity.AddClaim("urn:customclaim", "value", "token id_token");
var ticket = new AuthenticationTicket(
new ClaimsPrincipal(identity),
new AuthenticationProperties(),
context.Options.AuthenticationScheme);
// Call SetResources with the list of resource servers
// the access token should be issued for.
ticket.SetResources(new[] { "resource_server_1" });
// Call SetScopes with the list of scopes you want to grant
// (specify offline_access to issue a refresh token).
ticket.SetScopes(new[] { "profile", "offline_access" });
context.Validated(ticket);
return Task.FromResult<object>(null);
}
}
});
app.UseMvc();
}
}
project.json
{
"dependencies": {
"Microsoft.AspNet.Server.WebListener": "1.0.0-rc1-final",
"Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
"Microsoft.AspNet.Authentication.JwtBearer": "1.0.0-rc1-final",
"AspNet.Security.OpenIdConnect.Server": "1.0.0-beta4"
}
}
这篇关于IDX10503:签名验证失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!