"Это пшеница, что в темном чулане хранится, в доме, который построил Джек"
Джек имеет права на дом, а значит и на темный чулан, а стало быть и на пшеницу. Но чтобы проверить доступ Джека к пшенице, необходимо найти, в каком она хранится чулане, и в чьем доме этот чулан. Авторизация имеет линейную сложность от глубины иерархии объектов, и это плохо, т.к. всю цепочку объектов нужно читать из базы данных или держать в кеше. Становится еще хуже, если граф объектов имеет циклы и распределен между разными серверами.
Пример
Давайте рассмотрим систему управления задачами: в ней есть проекты и задачи. Проекты образуют иерархию: у каждого проекта может быть один или несколько родительских проектов. В проектах можно задавать права доступа, которые распространяются на все подпроекты. Система распределенная: родительский проект может быть расположен на другом сервере (в компании-контрагенте, например).
Требуется спроектировать процесс авторизации запросов пользователя к проектам и задачам, а также процесс изменения этих прав.
Мне известны два существующих пути решения этой задачи, восходящий и нисходящий:
При использовании нисходящего пути, изменения прав доступа распространяются на все вложенные ресурсы. Например, в Windows, так сделано изменение прав директории. Этот процесс может занять длительное время, возможно придется обращаться к другим серверам. Возникнут неприятные проблемы, если один из серверов окажется недоступен или в иерархии будут циклы. Зато проверка прав осуществляется быстро,
При восходящем пути список прав у каждого проекта свой и изменение выполняется быстро. Но проверка должна пройти по всей цепочке наследования снизу вверх, и этот путь может быть не короче нисходящего.
Существующие схемы авторизации (DAC, RBAC, ABAC...) обрабатывают каждый запрос независимо, исходя из данных аутентификации пользователя. Но пользователь может передавать серверу информацию о предыдущих авторизациях. Например, Джек получил в Росреестре свидетельство о праве на дом, затем в БТИ на основаниии этого свидетельства ему дали справку о владении чуланом. Теперь достаточно проверить, что пшеница хранится именно в указанном в справке чулане.
Inheritance-Based Access Control (IBAC)
Эта схема авторизации работает совместно с другой, базовой. Если права на доступ к ресурсу определены непосредственно для него, то работает базовая схема, а если наследуются от другого ресурса - то работает IBAC.

В ResourceToken хранится URI ресурса, время выдачи, полученные права, срок жизни и список ресурсов, которые позволили получить этот токен: ResourcePath.
На сервере хранятся сведения о наследовании прав доступа к ресурсам: InheritanceRule и сведения об инвалидации токенов Withdraw
ResourceToken будем считать валидным, если:
Он подписан закрытым ключем сервера;
Срок жизни токена еще не прошел;
Все ресурсы из ResourcePath отсутствуют среди Withdraw.
Авторизация доступа к ресурсу X считается успешной, если:
Базовая схема авторизации разрешила доступ, или;
В заголовках запроса был передан валидный ResourceToken ресурса X, или;
В заголовках запроса был передан валидный ResourceToken ресурса Y и cуществует InheritanceRule от ресурса Y к ресурсу X.
При успешной авторизации создается ResourceToken для ресурса X. ResourcePath выбирается следующим образом:
Если доступ авторизован посредством ResourceToken ресурса Y, то берем ResourcePath из этого токена и добавляет URI ресурса Y.
Если доступ авторизован посредством ResourceToken ресурса X, то берем ResourcePath из этого токена.
Иначе берем пустой список.
При удалении правила наследования прав доступа, необходимо добавить ресурс, который наследовал права, в список Withdraw на время максимального срока действия токена. Все токены, использовавшие этот ресурс для получения доступа к другим ресурсам, должны перестать работать.
Кажется, что этот алгоритм не очень-то и быстр: опять линейная сложность от глубины иерархии (длина ResourcePath), да еще и умноженная на длину списка Withdraw! Длина этого списка зависит от правил в системе. Например, для рассмотренной выше системы управления задач, она почти наверное равна нулю: если в системе и есть возможность перемещать проекты внутрь других проектов, то ей пользуются крайне редко. А если список Withdraw пуст, то и по ResourcePath проходить не нужно, и сложность константная.
А еще на Withdraw можно просто забить и доступ пропадет по истечению времени жизни токена, а пользователю можно сообщить, что изменение прав доступа займет 24 часа.
Возможности
Множественное наследование
Иногда появляются задачи, которые затрагивают несколько отделов компании. Приходится заводить проект, лежащий в нескольких проектах, но не всегда система позволяет это, в том числе из-за сложности авторизации. Если у проекта может быть несколько надпроектов, в реализации IBAC ничего не меняется. Даже в случае циклов (X → Y → X) проблемы скорей появятся на клиенте, чем на сервере.
Распределенные системы
Сейчас популярно отдавать проекты на аутсорс в другую компанию. Давайте сделаем систему управления задач распределенной: проекты могут храниться на разных серверах. Имея ResourceToken пользователь может получить доступ до проекта другой компании, но для этого сервера должны публиковать следующие сведения:
Публичный ключ для проверки подписи токенов.
Список Withdraw для проверки ResourcePath.
Все. Больше ничего менять не нужно. Список InheritanceRule хранится рядом с ресурсом, который наследует доступ (на том же сервере), поэтому легко доступен во время авторизации. Но, в этот случае придется все-таки пройти по ResourcePath и запросить Withdraw со всех необходимых серверов.
Микросервисы
В микросервисной архитектуре есть неудобство, что почти все сервисы зависят от сервиса авторизации. IBAC не удаляет эту зависимость, но ослабляет её: для проверки прав нужен только публичный ключ и список Withdraw.
Выводы
Спроектирована схема авторизации.
Работает почти наверное за O(1).
Может быть использована в распределенных системах.
Не боится множественного наследования и циклов.