Внедрить одну общую службу авторизации, которая должна вызываться, когда я помещаю в нее атрибут авторизации в нескольких приложениях /API.
Есть ли у кого-нибудь идея, что использовать в качестве общей службы авторизации, и есть пример рабочего кода или хорошие шаги по реализации, как реализовать такие вещи.
Мне нужно много времени, чтобы понять, что мне нужно, но пока не нашел удовлетворительного решения.
IdentityServer - это не вариант, а мои разрешения не могут быть сохранены как утверждения из-за размера токена. У него около 200 разрешений, поэтому это нужно делать в dbcontext или что-то в этом роде.
Я посмотрел на PolicyServer, но он работал не так, как я ожидал. Когда я установил его в приложении IS4, он работает на контроллерах IS4, но когда авторизация вызывается из внешнего приложения, он вообще не вызывает переопределение авторизации, если он должен проверять разрешения. И кажется, что разрешения не установлены во внешнем приложении ни в User.Claims, ни в чем-то еще. Думаю, мне не хватает некоторых настроек.
Я хочу добиться того, чтобы у меня было одно хранилище разрешений (таблица) (которое, например, содержит набор кнопок индекса, добавления, редактирования или удаления, или что-то еще). Он должен быть предоставлен авторизованному пользователю, который вошел в систему. Но это единое хранилище сохранений должно быть доступно во всех приложениях или API, которые я запускаю, чтобы атрибут Authorize мог выполнять свою работу.
Я думаю, что это не должно быть так сложно, поэтому мне не хватает хорошего рабочего примера, как реализовать что-то подобное и что работает. Кто может мне помочь в этом?
Я написал код, чтобы получить разрешения с помощью вызова API и использовать его в переопределении IsInRole. Но когда я объявляю это с помощью атрибута Authorize, он не попадает в метод:
[ApiController]
1) [Authorize]
public class AuthController : ControllerBase
{
private readonly IdentityContext _context;
public AuthController(IdentityContext context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
[HttpGet()]
[Route("api/auth/isinrole")]
public bool IsInRole(string role)
{
2) if (User.FindFirst("sub")?.Value != null)
{
var userID = Guid.Parse(User.FindFirst("sub")?.Value);
if([This is the code that checks if user has role])
return true;
}
return false;
Это переопределение IsInRole (переопределение ClaimsPrincipal.IsInRole):
public override bool IsInRole(string role)
{
var httpClient = _httpClientFactory.CreateClient("AuthClient");
3) var accessToken = _httpContextAccessor.HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken).Result;
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var request = new HttpRequestMessage(HttpMethod.Get, "/api/auth/isinrole/?id=" + role);
var response = httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).Result;
etc...
- Это не работает, пока он не отправляет access_token в запросе
- Подписка не отправляется
- Всегда ноль
2 ответа
Есть альтернатива вашему решению - использовать ссылочный токен вместо JWT-токена. Ссылочный токен - это просто непрозрачный идентификатор, и когда клиент получает этот токен, он должен перейти и найти настоящий токен и детали через бэкэнд. Ссылочный токен не содержит никакой информации. Это просто идентификатор поиска, который клиент может использовать против IdentiyServer
Используя это, ваши токены будут очень маленькими.
Использование ссылочного токена - лишь один из доступных вам вариантов.
см. документацию по ссылочным токенам
Версия PolicyServer с открытым исходным кодом является локальной реализацией. Все, что он делает, - это считывает разрешения из магазина (в примере это файл конфигурации) и преобразует их в утверждения с помощью промежуточного программного обеспечения.
Чтобы использовать разрешения, вам нужно будет добавить это промежуточное ПО во все проекты, в которых вы хотите использовать разрешения.
Имея локальные разрешения, у вас не может быть конфликтов с другими ресурсами. Например, если вы являетесь администратором в api1, это не означает, что вы также являетесь администратором в api2.
Но поддерживать децентрализованные разрешения может быть сложно. Вот почему вам, вероятно, понадобится центральный сервер для разрешений, где хранилище фактически вызывает сервер политики, а не читает разрешения из локального файла конфигурации.
Для этого вам нужно добавить дискриминатор, чтобы различать ресурсы. Я использую области видимости, потому что это единственное, что разделяют и клиент, и ресурс.
Он также сохраняет небольшой размер ответа, вам нужно только запросить разрешения для определенной области вместо всех разрешений.
Альтернативой является использование IdentityServer как есть. Но вместо токенов JWT используйте ссылочные токены.
Случайная строка намного короче, но требует, чтобы клиент и / или ресурс запрашивали разрешения, отправляя ссылочный токен на IdentityServer. Это может быть похоже на то, как работает PolicyServer, но с меньшим контролем над ответом.