Авторизуйтесь через JWT Token
ASP.NET Core 5 с ASP.NET Identity 3.0, я использую как веб-страницы, так и API-интерфейсы. Я использую OpenIddict для выдачи токена JWT и аутентификации. Мой код выглядит так:
X509Certificate2 c = new X509Certificate2(@"tokensign.p12", "MyCertificatePassword");
services.AddOpenIddict<WebUser, IdentityRole<int>, WebDbContext, int>()
.EnableTokenEndpoint("/api/customauth/login")
.AllowPasswordFlow()
.UseJsonWebTokens()
.AddSigningCertificate(c);
Если я отключу UseJsonWebTokens(), я могу сгенерировать токен и успешно авторизоваться. Однако я не уверен, что мой сертификат проверяет возвращенные токены.
А при включении UseJsonWebTokens я могу выдать токен JWT в этой конечной точке. Однако я не могу подтвердить подлинность любого запроса!
Я использую следующий код в конфигурации приложения:
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
RequireHttpsMetadata = false,
Authority = "http://localhost:60000/",
Audience = "http://localhost:60000/",
});
app.UseOAuthValidation();
app.UseIdentity();
app.UseOpenIddict();
app.UseMvcWithDefaultRoute();
- Как я могу заставить запрос быть проверенным с моим сертификатом, чтобы убедиться, что токен JWT не подделан.
- Каковы правильные настройки, которые позволят проверять и авторизовать мой токен JWT, учитывая, что если я не использую JWT, я получаю авторизацию успешно.
1 ответ
Если я отключу UseJsonWebTokens(), я могу сгенерировать токен и успешно авторизоваться. Однако я не уверен, что мой сертификат проверяет возвращенные токены.
В ASOS (серверная структура OpenID Connect за OpenIddict) есть 2 различных встроенных механизма сериализации для создания и защиты токенов:
- Тот, который использует IdentityModel (библиотека, разработанная Microsoft) и производит стандартные токены, проверяемые третьими сторонами:
Идентификационные токены (по определению JWT) всегда создаются с использованием этого процесса, и вы можете вызвать UseJsonWebTokens()
заставить OpenIddict выдавать токены доступа, которые используют тот же процесс сериализации.
Сертификат, который вы указываете при звонке AddSigningCertificate()
всегда используется для подписи этих токенов.
- Тот, который использует стек ASP.NET Core Data Protection (также разработанный Microsoft):
Этот стек создает исключительно "проприетарные" токены, которые не предназначены для чтения или проверки третьей стороной, поскольку формат токена не является стандартным и обязательно основан на симметричном подписывании и шифровании.
Это механизм, который мы используем для кодов авторизации и обновления токенов, которые предназначены только для использования самим OpenIddict. Он также используется для токенов доступа, когда вы используете формат токенов по умолчанию.
В этом случае сертификат вы указываете при звонке AddSigningCertificate()
не используется
Вместо этого эти токены всегда шифруются стеком защиты данных с использованием Authenticated Encryption
алгоритм (по умолчанию AES-256-CBC с HMACSHA256), обеспечивающий подлинность, целостность и конфиденциальность. Для этого 2 ключа (один для шифрования, один для проверки) выводятся из стека защиты данных из одного из главных ключей, хранящихся в кольце ключей.
Как я могу заставить запрос быть проверенным с моим сертификатом, чтобы убедиться, что токен JWT не подделан. Каковы правильные настройки, которые позволят проверять и авторизовать мой токен JWT, учитывая, что если я не использую JWT, я получаю авторизацию успешно.
Чтобы ответить на эти вопросы, было бы полезно, если бы вы включили ведение журнала и поделились своими следами.
Создать аутентификацию на основе токена JWT в ASP.NET Core очень просто. Пожалуйста, перейдите по ссылке ниже, чтобы получить больше информации. Как создать токен JWT в Asp NET Core
Образец кода
public static class AuthenticationConfig
{
public static string GenerateJSONWebToken(string user)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("730F046B1ADF1555FF0C80149B47B38CD7C0A146AAFA34870E863CAA25B585C3"));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[] {
new Claim("UserName", user),
new Claim("Role", "1"),
};
var token = new JwtSecurityToken("http://localhost:30972",
"http://localhost:30972",
claims,
DateTime.UtcNow,
expires: DateTime.Now.AddMinutes(10),
signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(token);
}
//ConfigureJwtAuthentication
internal static TokenValidationParameters tokenValidationParams;
public static void ConfigureJwtAuthentication(this IServiceCollection services)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("730F046B1ADF1555FF0C80149B47B38CD7C0A146AAFA34870E863CAA25B585C3"));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
tokenValidationParams = new TokenValidationParameters()
{
ValidateIssuerSigningKey = true,
ValidIssuer = "http://localhost:30972",
ValidateLifetime = true,
ValidAudience = "http://localhost:30972",
ValidateAudience = true,
RequireSignedTokens = true,
// Use our signing credentials key here
// optionally we can inject an RSA key as
//IssuerSigningKey = new RsaSecurityKey(rsaParams),
IssuerSigningKey = credentials.Key,
ClockSkew = TimeSpan.FromMinutes(10)
};
services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = tokenValidationParams;
#if PROD || UAT
options.IncludeErrorDetails = false;
#elif DEBUG
options.RequireHttpsMetadata = false;
#endif
});
}
}
Добавьте эту строку в Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.ConfigureJwtAuthentication();
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme).RequireAuthenticatedUser().Build();
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
Добавьте эти строки в Контроллер аутентификации
[Route("api/[controller]")]
public class AuthenticationController : Controller
{
// GET: api/<controller>
[HttpGet]
public string Get(string user, string pass)
{
if (user == "admin")
{
return AuthenticationConfig.GenerateJSONWebToken(user);
}
else
{
return "";
}
}
// POST api/<controller>
[Authorize]
[HttpPost]
public string Post()
{
var identity = HttpContext.User.Identity as ClaimsIdentity;
IEnumerable<Claim> claim = identity.Claims;
var UserName = claim.Where(c => c.Type == "UserName").Select(c => c.Value).SingleOrDefault();
return "Welcome to " + UserName + "!";
}
}