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