Реализация по умолчанию JWT - PullRequest
0 голосов
/ 05 февраля 2019

Я создаю приложение, которое использует 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 Token Generation.Мне не нужно ничего слишком сумасшедшего, как IdentityServer (мне не нужно обрабатывать несколько клиентов).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...