代码之家  ›  专栏  ›  技术社区  ›  johnny 5

JWT的默认实现

  •  0
  • johnny 5  · 技术社区  · 7 年前

    我正在创建一个使用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);
    

    我找到了一家jwtfactory,可以在线创建令牌,如下所示:

    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标准化的方法来做这件事

    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 回复  |  直到 7 年前