JWT的默认实现

时间:2019-02-05 00:40:09

标签: c# asp.net-core jwt

我正在创建一个使用OAuth进行第三方身份验证的应用。我想将其与JWT一起使用,但是我使用的解决方案有问题,我会采用更为标准化的方式。

我有一个启动配置,该配置使用OAuth登录并作为我的身份验证架构:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(cfg =>
    {
        cfg.RequireHttpsMetadata = false;
        cfg.SaveToken = true;

        cfg.TokenValidationParameters = tokenValidationParameters;
    })
    .AddCoinbase(options => {
        options.SendLimitCurrency = "USD";
        options.ClientId = Configuration["Coinbase:ClientId"];
        options.ClientSecret = Configuration["Coinbase:ClientSecret"];
        COINBASE_SCOPES.ForEach(scope => options.Scope.Add(scope));
        options.SaveTokens = true;
        options.ClaimActions.MapJsonKey("urn:coinbase:avatar", "avatar_url");
    });

用户登录时,他们将通过帐户控制器中的默认质询逻辑。

[HttpPost("ExternalLogin")]
[AllowAnonymous]
public IActionResult ExternalLogin(string provider, string returnUrl = null)
{
    var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { returnUrl });
    var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
    return Challenge(properties, provider);
}

在我的外部登录中,必须生成我自己的令牌非常烦人,我认为这可以通过某些默认逻辑来完成。 注意,为简单起见,省略了一些逻辑

[HttpGet("ExternalLoginCallback")]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
    var info = await _signInManager.GetExternalLoginInfoAsync();
    var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);

    var user = await (result.Succeeded ?
         _userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey)
        : this.CreateIdentityUser(info));

    var jwt = await Tokens.GenerateJwt(_jwtFactory.GenerateClaimsIdentity(user.UserName, user.Id),
            _jwtFactory, _jwtOptions);

我找到了一个在线创建令牌的工厂,如下所示:

public class JwtFactory : IJwtFactory
{
    //... More Code
    public async Task<string> GenerateEncodedToken(string userName, ClaimsIdentity identity)
    {
        var claims = new[]
        {
             new Claim(JwtRegisteredClaimNames.Sub, userName),
             new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()),
             new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64),
             identity.FindFirst(Constants.JwtClaimIdentifiers.Rol),
             identity.FindFirst(Constants.JwtClaimIdentifiers.Id)
         };

        // Create the JWT security token and encode it.
        var jwt = new JwtSecurityToken(
            issuer: _jwtOptions.Issuer,
            audience: _jwtOptions.Audience,
            claims: claims,
            notBefore: _jwtOptions.NotBefore,
            expires: _jwtOptions.Expiration,
            signingCredentials: _jwtOptions.SigningCredentials);

        var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);

        return encodedJwt;
    }

    public ClaimsIdentity GenerateClaimsIdentity(string userName, string id)
    {
        return new ClaimsIdentity(new GenericIdentity(userName, "Token"), new[]
        {
            new Claim(Constants.JwtClaimIdentifiers.Id, id),
            new Claim(Constants.JwtClaimIdentifiers.Rol, Constants.JwtClaims.ApiAccess)
        });
    }
    //... More code
}

public class Tokens
{
    public static async Task<string> GenerateJwt(ClaimsIdentity identity, IJwtFactory jwtFactory, 
        JwtIssuerOptions jwtOptions, JsonSerializerSettings serializerSettings = null)
    {
        serializerSettings = serializerSettings ?? new JsonSerializerSettings { Formatting = Formatting.Indented };

        var id = identity.Claims.Single(c => c.Type == "id").Value;
        var response = new
        {
            id = id,
            auth_token = await jwtFactory.GenerateEncodedToken(id, identity),
            expires_in = (int)jwtOptions.ValidFor.TotalSeconds
        };

        return JsonConvert.SerializeObject(response, serializerSettings);
    }
}

这个JWTFactory似乎可以使这种逻辑通用,我想知道是否还有更多的.net stardarized方法来执行此操作,例如

services.AddSingleton<ITokenGenerator>(sp => {

    var claimsMap = new ClaimsMap();
    claimsMap.AddFromIdentity(JwtRegisteredClaimNames.Sub, x => x.UserName);
    var tokenGenerator = new Microsoft.AspNetCore.Authentication.JWT.TokenGenerator(claimsMap);
});

基本上,我正在寻找一种更加标准化的轻量级方法来处理JWT令牌生成。我不需要像IdentityServer这样太疯狂的东西(不需要处理多个客户端)。

0 个答案:

没有答案