通过JWT Token授权

时间:2016-07-23 12:27:02

标签: asp.net-core jwt openid-connect aspnet-contrib openiddict

使用ASP.NET Identity 3.0的ASP.NET Core 5,我正在使用网页和apis。我正在使用OpenIddict发出JWT令牌并进行身份验证。我的代码看起来像这样:

    X509Certificate2 c = new X509Certificate2(@"tokensign.p12", "MyCertificatePassword");

    services.AddOpenIddict<WebUser, IdentityRole<int>, WebDbContext, int>()
        .EnableTokenEndpoint("/api/customauth/login")
        .AllowPasswordFlow()
        .UseJsonWebTokens()
        .AddSigningCertificate(c);

如果禁用UseJsonWebTokens(),我可以生成令牌并成功授权。但是,我不确定我的证书是否验证了返回的令牌。

当启用UseJsonWebTokens时,我能够在此终点发出JWT令牌。但是,我无法验证任何请求!

我在应用配置中使用以下代码:

    app.UseJwtBearerAuthentication(new JwtBearerOptions
    {
        AutomaticAuthenticate = true,
        AutomaticChallenge = true,
        RequireHttpsMetadata = false,
        Authority = "http://localhost:60000/",
        Audience = "http://localhost:60000/",
    });
    app.UseOAuthValidation();
    app.UseIdentity();
    app.UseOpenIddict();
    app.UseMvcWithDefaultRoute();
  • 如何强制使用我的证书验证请求,以确保JWT令牌未被篡改。
  • 允许验证和授权我的JWT令牌的正确设置是什么,因为如果我不使用JWT,我将获得成功授权。

2 个答案:

答案 0 :(得分:5)

  

如果禁用UseJsonWebTokens(),我可以生成令牌并成功授权。但是,我不确定我的证书是否验证了返回的令牌。

在ASOS(OpenIddict背后的OpenID Connect服务器框架)中,有2种不同的内置序列化机制来创建和保护令牌:

  • 使用IdentityModel (由Microsoft开发的库)生成可由第三方验证的标准令牌

始终使用此过程创建标识令牌(根据定义为JWT),您可以调用UseJsonWebTokens()强制OpenIddict发出使用相同序列化过程的访问令牌。

您在调用AddSigningCertificate()时指定的证书始终用于签署这些令牌。

  • 使用ASP.NET核心数据保护堆栈的人(也是由Microsoft开发的):

此堆栈专门生成“专​​有”令牌,这些令牌不打算由第三方读取或验证,因为令牌格式不是标准格式,必然依赖于对称签名和加密。 / p>

这是我们用于授权代码和刷新令牌的机制,仅供OpenIddict本身使用。当您使用默认令牌格式时,它也用于访问令牌。

在这种情况下,不使用您在调用AddSigningCertificate()时指定的证书。

相反,这些令牌始终由数据保护堆栈使用Authenticated Encryption算法(默认情况下为AES-256-CBC和HMACSHA256)加密,提供真实性,完整性和机密性。为此,2个密钥(一个用于加密,一个用于验证)由数据保护堆栈从存储在密钥环中的一个主密钥导出。

  

如何强制使用我的证书验证请求,以确保JWT令牌未被篡改。   什么是允许验证和授权我的JWT令牌的正确设置,因为如果我没有使用JWT,我将获得成功授权。

要回答这些问题,如果您启用了日志记录并共享了跟踪,这将有所帮助。

答案 1 :(得分:0)

在ASP.NET Core中创建基于JWT令牌的身份验证非常简单。请点击以下链接,您将获得更多的想法。 How to Create JWT Token in Asp NET Core

示例代码

public static class AuthenticationConfig
{
    public static string GenerateJSONWebToken(string user)
    {
        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("730F046B1ADF1555FF0C80149B47B38CD7C0A146AAFA34870E863CAA25B585C3"));
        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        var claims = new[] {
             new Claim("UserName", user),
              new Claim("Role", "1"),
                };

        var token = new JwtSecurityToken("http://localhost:30972",
          "http://localhost:30972",
          claims,
          DateTime.UtcNow,
          expires: DateTime.Now.AddMinutes(10),
          signingCredentials: credentials);

        return new JwtSecurityTokenHandler().WriteToken(token);
    }

    //ConfigureJwtAuthentication
    internal static TokenValidationParameters tokenValidationParams;
    public static void ConfigureJwtAuthentication(this IServiceCollection services)
    {
        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("730F046B1ADF1555FF0C80149B47B38CD7C0A146AAFA34870E863CAA25B585C3"));
        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        tokenValidationParams = new TokenValidationParameters()
        {
            ValidateIssuerSigningKey = true,
            ValidIssuer = "http://localhost:30972",
            ValidateLifetime = true,
            ValidAudience = "http://localhost:30972",
            ValidateAudience = true,
            RequireSignedTokens = true,
            // Use our signing credentials key here
            // optionally we can inject an RSA key as
            //IssuerSigningKey = new RsaSecurityKey(rsaParams),
            IssuerSigningKey = credentials.Key,
            ClockSkew = TimeSpan.FromMinutes(10)
        };
        services.AddAuthentication(options =>
        {
            options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
        })

        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = tokenValidationParams;
            #if PROD || UAT
                  options.IncludeErrorDetails = false;
            #elif DEBUG
                  options.RequireHttpsMetadata = false;
            #endif
        });
    }
}

在Startup.cs中添加此行

 public void ConfigureServices(IServiceCollection services)
    {
        services.ConfigureJwtAuthentication();
        services.AddAuthorization(options =>
        {
            options.DefaultPolicy = new  AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme).RequireAuthenticatedUser().Build();
        });
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

在身份验证控制器中添加这些行

[Route("api/[controller]")]
public class AuthenticationController : Controller
{
    // GET: api/<controller>
    [HttpGet]
    public string Get(string user, string pass)
    {
        if (user == "admin")
        {
            return AuthenticationConfig.GenerateJSONWebToken(user);
        }
        else
        {
            return "";
        }

    }


    // POST api/<controller>
    [Authorize]
    [HttpPost]
    public string Post()
    {
        var identity = HttpContext.User.Identity as ClaimsIdentity;
        IEnumerable<Claim> claim = identity.Claims;
        var UserName = claim.Where(c => c.Type == "UserName").Select(c => c.Value).SingleOrDefault();

        return "Welcome to " + UserName + "!";
    }


}