Мне нужно обработать токен безопасности в минимальном веб-API. Это правильный подход?
Я экспериментирую с минимальными веб-API, когда хочу создать веб-сайт, использующий статические веб-страницы с дополнительным API, предоставляющим всевозможные функции, которые можно вызывать как с сайта, так и из отдельного приложения. Это для многопользовательского веб-сайта, который работает на нескольких доменах и множестве поддоменов. Каждый (суб)домен будет иметь свой собственный статический контент, и он создается пользователями, а не мной. Все, что я делаю, это предоставляю среду хостинга и дополнительные веб-API.
Одной из существующих функций является API входа/выхода из системы. При этом используется носитель JWT и токен JWT, которые я возвращаю как значение файла cookie, так и заголовок. Почему? Поскольку веб-браузеры будут использовать файл cookie, а приложения могут использовать значение заголовка. У них обоих один и тот же токен. Этот токен содержит некоторую базовую информацию о пользователе, такую как имя (не имя пользователя) и адрес электронной почты пользователя, а также хост, на котором пользователь вошел в систему. Мой бэкенд не хранит имена пользователей, поскольку имя пользователя и пароль преобразуются в один хэш. Этот хеш хранится вместе с пользовательскими данными, если пользователь их предоставил. (Все пользовательские данные являются необязательными.)
Сайт не обрабатывает никаких важных данных, но используется в качестве тренировочной арены для веб-разработчиков интерфейса.
Теперь у меня есть эта услуга:
builder
.Services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Events = new JwtBearerEvents()
{
OnMessageReceived = context =>
{
if (context.Request.Cookies.ContainsKey(configuration.Bearer.Cookie))
{
context.Token = context.Request.Cookies[configuration.Bearer.Cookie];
}
else if (context.Request.Headers.ContainsKey(configuration.Bearer.Cookie))
{
context.Token = context.Request.Headers[configuration.Bearer.Cookie];
}
return Task.CompletedTask;
}
};
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = configuration.Bearer.Issuer,
ValidAudience = configuration.Bearer.Audience,
IssuerSigningKey = new SymmetricSecurityKey(configuration.Bearer.SecretKey),
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = false,
ValidateIssuerSigningKey = true
};
});
А configuration.Bearer — это просто контейнер данных для эмитента, имени куки и т. д. Это работает хорошо, но проблема в том, что я хочу возвращать этот токен JWT при каждом вызове в заголовке, кроме как в функции выхода из системы:
app
.MapGet("/Logout", (HttpContext context) =>
{
context.Response.Cookies.Delete(configuration.Bearer.Cookie);
return Redirect("/");
}).RequireAuthorization();
Выход из системы просто говорит браузеру удалить файл cookie.
Но теперь я хочу добавить еще один промежуточный слой, чтобы обновить этот токен с немного более длительным сроком действия, поэтому у меня есть это:
app
.Use(async (HttpContext context, Func<Task> next) =>
{
// Something here?
await next();
// Something here?
});
И это промежуточное программное обеспечение должно получить токен, установить срок действия сейчас плюс 5 минут и вернуть этот новый токен в виде файла cookie и значения заголовка. (Но только если для начала был токен.) Таким образом, активный пользователь остается в системе, в то время как неактивный пользователь должен войти в систему через 5 минут.
Это правильный подход? И как мне добавить эти токены в куки и заголовок здесь? (И обновить время ожидания?)