Comments 11
Мы тоже пытались реализовать авторизацию (не путать с аутентификацией - с ней всё норм) через Keycloak, но не взлетело. Например, как банально получить перечень записей, но отфильтровать те, к которым у пользователя нет доступа? Запрашивать все записи и потом по каждой отправлять запрос в Keycloak? Как это всё будет стыковаться с пагинацией? Допустим на странице должно быть 10 записей, из них доступ есть только к 7. Нужно дозапросить ещё 3 записи?..
Я просто не понимаю как это может работать хоть для сколько-нибудь сложного приложения. Хотя сам Keycloak клёвый. У нас приложение вместе с Keycloak, ApacheDS (для тестовых пользователей) и т.д. завернуто в Docker Compose. При запуске Keycloak автоматически импортируется json-конфиг с настройками realm, интеграцией с ApacheDS. Всё это легко разворачивается на стенде, на машинах разработчиков, в тестовом окружении.
Как вариант можно написать свой плагин, который будет имплементировать нужный Вам АПИ ендпоинт.
Всё равно останется проблема, что записи в одном сервисе (само приложение), а разрешения для них - в другом (Keycloak). И нужно получать данные из двух источников, как-то мержить их. Здесь в принципе не сделать простую и быструю реализацию. Гораздо проще хранить и записи, и разрешения в одной базе и получать всё одним SQL-запросом.
Например, как банально получить перечень записей, но отфильтровать те, к которым у пользователя нет доступа? Запрашивать все записи и потом по каждой отправлять запрос в Keycloak? Как это всё будет стыковаться с пагинацией? Допустим на странице должно быть 10 записей, из них доступ есть только к 7. Нужно дозапросить ещё 3 записи?..
Мы у себя запрашиваем доступные scope для нужного нам ресурса и дальше уже подставляем нужные фильтры в сам запрос.
Не очень понимаю... Если нужно ограничить доступ по типам ресурсов, то можно использовать роли из Keycloak. Например, одна роль позволяет просматривать новости, другая - статьи.
Немного более сложный вариант. Допустим статьи могут быть двух типов: обычные для всех и премиальные для подписчиков. Это тоже можно решить через роли "обычный пользователь", "подписчик", "супер-подписчик" и т.д.
А если ещё более сложный вариант типа Google Документов? Пользователи могут создавать документы, выдавать к ним доступ другим пользователям. Причём, этих документов в системе миллионы. В Keycloak должна храниться информация о каждом таком документе? Затем в него отправляется запрос с id документа и id пользователя и Keycloak отвечает есть ли у пользователя доступ к этому документу?
Вы меня не поняли.
В Keycloak для авторизации есть две сущности:
Ресурсы.
Область действий.
Например есть у нас ресурс (resource): статьи.
И область действий (scope): читать и чтение за деньги. Которую назначаем для ресурса и привилегий.
Представим что у нас есть пользователи с платным доступом и бесплатным.
Соответственно с платным могут читать все статьи, а с бесплатным только бесплатные.
В backend делаю запрос в keycloak на получение доступных областей пользования для текущего пользователя и ресурса. Keycloak возращает массив.
Далее перед запросом списка статей из репозитория\БД, проверяю каждую область действий по отдельности:
Могу видеть все статьи? - Если да, то делаем запрос без фильтров и условий.
Могу видеть платные статьи? - Если нет, то ограничиваем тип статей.
Могу видеть бесплатные статьи? Если нет, то выдаю ошибку 403.
Моя реализация может быть не правильной.
Роли нам не совсем подходят, так как нужен гибкий инструмент для настройки политик и пермиссий.
Спасибо, теперь кажется понял. По сути resource и scope - это возможно чуть более правильный вариант по сравнению с ролями. Но пообъектную проверку доступа через него всё равно не сделать.
Или пообъектной проверки и нет в Keycloak вообще? Интересно что имеется в виду под ресурсом в документации на сервер авторизации. Это типы ресурсов, например, "обычная статья", "платная статья" и т.д.? Или речь о конкретных ресурсах: "статья с идентификатором 123 про Keycloak", "статья с ид 234 про OIDC" и т.д.? Или ресурсом может быть что угодно: и тип ресурсов, и конкретный ресурс?
То, что в Keycloak можно описать правила доступа к типам ресурсов это понятно. Либо через роли, либо через скоупы. Но если нужно разделение доступа на уровне отдельных объектов, то по-моему Keycloak уже не очень подходит.
Интересно что имеется в виду под ресурсом в документации на сервер авторизации. Это типы ресурсов, например, "обычная статья", "платная статья" и т.д.?
Статья - это и есть ресурс. Это может быть что-то абстрактное.
Например помимо статей, есть ещё новости. Можно разбить на меньшие понятия, например научные и развлекательные статьи.
"платный", можно выделить к scope
(мы так у себя сделали назвав примерно как view_paid
), но ни что не мешает сделать как resource
.
Но если нужно разделение доступа на уровне отдельных объектов, то по-моему Keycloak уже не очень подходит.
Мы в будущем планируем писать свой велосипед, из-за того что есть кейсы, которые Keycloak не может разрешить. Будем конечно ещё копаться.
Видимо это меня и сбивает, потому что обычно под ресурсом подразумевается конкретный объект. Например, в REST это может быть ресурсами:
https://example.com/api/articles/1
https://example.com/api/articles/2
https://example.com/api/articles/3
...
А статьи, новости и т.д. - это типы ресурсов, а не конкретные ресурсы. Или допустим в документации упоминается "fine-grained authorization", "fine-grained permissions" - у меня сразу возникают ассоциации с ограничением доступа на уровне отдельных объектов или даже отдельных атрибутов, с чем-нибудь типа Row-Level Security, но реально имеется в виду что-то более простое.
Ну либо я не совсем верно понял.
Вот гайд по которому мы реализовывали у себя пермиссии: https://www.keycloak.org/docs/latest/authorization_services/index.html#resource
Там они пишут что это может быть как в целом "банковский счёт", так и конкретный "банковский счёт Алисы".
Да, по ссылке написано:
Every resource has a unique identifier that can represent a single resource or a set of resources. For instance, you can manage a Banking Account Resource that represents and defines a set of authorization policies for all banking accounts. But you can also have a different resource named Alice’s Banking Account, which represents a single resource owned by a single customer, which can have its own set of authorization policies.
Т.е. под ресурсом они имеют в виду и коллекцию (тип) ресурсов, и конкретные ресурсы.
Но сложно представить банковскую систему с миллионом пользователей, у каждого из которых есть свои банковские счета. И чтобы собственные правила доступа к каждому из этих миллионов счетов хранились в Keycloak.
Цикл постов про Keycloak. Часть вторая: Контроль доступа на уровне приложения