使用AuthenticateAsync生成JWT令牌

时间:2017-08-23 20:41:36

标签: jwt claims-based-identity claims .net-core-2.0

我正在尝试使用ClaimsPrincipal登录,然后在.net core 2.0中获取JWT。使用我当前的代码,我从SignInAsync函数的结果中得到错误: “没有IAuthenticationSignInHandler配置为处理该方案的登录:承载”

这是我目前使用的控制器:

[Route("Login/{username}")]
public async Task<IActionResult> Login(string username)
{
    var userClaims = new List<Claim>
    {
        new Claim(ClaimTypes.Name, username)
    };
    var principal = new ClaimsPrincipal(new ClaimsIdentity(userClaims));
    var sign = HttpContext.SignInAsync(principal);
    await sign;
    var res = await HttpContext.AuthenticateAsync();
    var token = await HttpContext.GetTokenAsync("access_token");
    return Json(token);
}

登录部分经过测试,适用于Cookie。但是,当我在startup.cs中使用以下代码JwtBearerDefaults.AuthenticationScheme时:

services.AddAuthentication(config => {
    config.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    config.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(config =>
{
    config.TokenValidationParameters = Token.tokenValidationParameters;
    config.RequireHttpsMetadata = false;
    config.SaveToken = true;
});

我从SignInAsync函数的结果中得到错误: “没有IAuthenticationSignInHandler配置为处理该方案的登录:承载”

My Token类是借助我在网上找到的代码(JWT on .NET Core 2.0)创建的,定义如下:

public static class Token
{

    public static TokenValidationParameters tokenValidationParameters {
        get
        {

            return new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = GetSignInKey(),
                ValidateIssuer = true,
                ValidIssuer = GetIssuer(),
                ValidateAudience = true,
                ValidAudience = GetAudience(),
                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero
            };
        }
    }

    static private SymmetricSecurityKey GetSignInKey()
    {
        const string secretKey = "very_long_very_secret_secret";
        var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));

        return signingKey;
    }

    static private string GetIssuer()
    {
        return "issuer";
    }

    static private string GetAudience()
    {
        return "audience";
    }

}

2 个答案:

答案 0 :(得分:3)

如果我从查看JwtBearerHandler的源代码中正确理解它,它就不会实现IAuthenticationSignInHandler,这就是你收到此错误的原因。调用SignInAsync旨在持久化身份验证信息,例如创建的auth cookie,例如,这正是CookieAuthenticationHandler所做的。但是对于JWT来说,没有一个众所周知的存储令牌的地方,因此根本没有理由调用SignInAsync。取而代之的是,抓取令牌并将其传递回浏览器。假设您正在重定向,您可以将其放入查询字符串中。假设浏览器应用程序是SPA(即基于Angular的)并且您需要用于AJAX调用的令牌,则应将令牌存储在SPA中并随每个API请求一起发送。有一些关于如何将JWT与不同类型的SPA一起使用的好教程,例如:https://medium.com/beautiful-angular/angular-2-and-jwt-authentication-d30c21a2f24f

请记住,JwtBearerHandler期望在其中找到带有Bearer的Authentication头,因此如果您的AJAX调用将令牌放在查询字符串中,您将需要提供JwtBearerEvents.OnMessageReceived实现,该实现将从查询字符串中获取令牌并将其放入标题。

答案 1 :(得分:1)

可以使用JwtSecurityTokenHandler创建签名的令牌。

var handler = new JwtSecurityTokenHandler();
var jwt = handler.CreateJwtSecurityToken(new SecurityTokenDescriptor
{
     Expires = DateTime.UtcNow.Add(Expiary),
     Subject = new ClaimsIdentity(claims, "local"),
     SigningCredentials = new SigningCredentials(SigningKey, SecurityAlgorithms.HmacSha256)
});
return handler.WriteToken(jwt);