Сомнения Open Id Connect - Identity Server 4 // Как предоставить конкретным пользователям конкретные области? - PullRequest
0 голосов
/ 02 января 2019

У меня есть некоторые сомнения после прочтения документов Open Id.Любая помощь будет принята с благодарностью.

После любого из потоков oidc у вас заканчиваются id_token и access_token.

a) Когда вы отправляете access_token защищенному API, почему или когда (пример) ему потребуется получить некоторые утверждения о пользователе, которому он принадлежит?Может быть, если защищенный API хочет использовать некоторые данные об аутентифицированном пользователе?

b) Для получения утверждений защищенный API должен будет связаться с конечной точкой UserEdnpoint?Он отправляет access_token?И какие утверждения содержатся в возвращенном id_token? / Что произойдет, если он запросит дополнительные утверждения о том, что пользователь имеет согласный доступ?

c) Сервер идентификации 4: Вы определяете ресурсы, которые должны быть защищены.Это могут быть «ресурсы идентификации» и «ресурсы API». При определении ApiResources, которые вы можете определить внутри детализированных областей.Например:

  Scopes =
        {
            new Scope()
            {
                Name = "weather.api.full_access",
                DisplayName = "Full access to WEATHER API",
            },
            new Scope
            {
                Name = "weather.api.read_only",
                DisplayName = "Read only access to WEATHER API"
            }
        }

Также вы определяете клиентов и к каким областям они имеют доступ.Как вы определяете, какие пользователи могут получить доступ к определенным ресурсам?Я не понимаю, как вы будете отображать определенные разрешения пользователей, использующих один и тот же клиент.

Шаги будут:

  1. Предоставить клиенту доступ к обеим областям: "weather.api.full_access "," weather.api.read_only "
  2. А теперь .... как я могу предоставить, например," Billy ", чтобы иметь" weather.api.full_access ", и" Jhon ", чтобы иметь" weather ".api.read_only "?Они используют один и тот же клиент.

Большое спасибо !!

Ответы [ 2 ]

0 голосов
/ 03 января 2019

IdentityServer состоит из трех частей:

  1. Конфигурация ApiResource
  2. Конфигурация IdentityResource
  3. Информация о пользователе (претензии)

Существует два токена: токен доступа и токен идентификации. Токен доступа используется для доступа к ресурсам (api, а также конечной точке UserInfo), идентификационный токен содержит информацию о пользователе.

Хотя IdentityServer предназначен для аутентификации пользователя, он также содержит конфигурацию для авторизации. Вы можете использовать что-то вроде PolicyServer, чтобы убрать авторизацию из IdentityServer, но для базовой авторизации вам это не нужно.

Существует два типа пользовательских утверждений:

  1. утверждает, кто пользователь, например, имя, пол, день рождения и т. Д.
  2. утверждения о том, на что пользователь имеет права, например роли, employeeId и т. Д.

Первый набор утверждений является частью идентификационного токена и сообщает клиенту о ВОЗ, которой является пользователь, другие утверждения являются частью токена доступа и сообщают API, что пользователю разрешено делать.

Что касается Identity Token, единственное, на что вы можете рассчитывать, это тот факт, что он всегда содержит утверждение sub (идентификатор из таблицы пользователя). Краткая версия философии здесь - держать маркер маленьким, потому что все, что вам нужно, - это утверждение. Дополнительная информация может быть запрошена в конечной точке UserInfo. Содержание идентификатора токена может различаться. Например. вы можете принудительно добавить все утверждения к первому токену (AlwaysIncludeUserClaimsInIdToken), чтобы предотвратить дополнительный вызов.

С другой стороны, если пользователь решит не давать согласие, маркер идентификации останется пустым (за исключением подпретензии, поскольку требуется область действия = openid). Также при запросе от конечной точки UserInfo.

Итак, вопрос в том, как вы собираетесь использовать идентификационный токен? Какую ценность имеет токен? Вы не должны использовать его для доступа к ресурсам (вот для чего нужен токен доступа), и он может не содержать запрошенную информацию.

Что касается токена доступа, это токен, который фактически позволяет клиенту получить доступ к ресурсу (api). В потоке client_credentials нет пользователя (поэтому также не будет идентифицирующего токена), тогда как в других случаях клиент будет действовать от имени пользователя. Разница между первым потоком и остальными - это утверждение sub. Это сообщает API, от чьего имени клиент запрашивает доступ.

Поскольку токены доступа учитываются одинаково, если пользователь не дает согласия, клиент не сможет получить доступ к ресурсу.

О ресурсах и областях применения. Ресурс - это логическое имя ресурса. Под этим я подразумеваю, что возможно, что у вас есть несколько API, которые являются частью одного и того же ресурса. Все в порядке. Потому что один ресурс может иметь много областей. В примерах это 1: 1, но когда вы действительно используете области действия, вы увидите, что область действия фактически определяет определенную часть функциональности в ресурсе. Как микро услуги.

Вернуться к IdentityServer. Важной задачей IdentityServer является фильтрация претензий. Потому что у пользователя может быть много претензий, но вы хотите их только тогда, когда они вам нужны. Таким образом, к токену добавляются запрошенные претензии.

Заявления Identity Token что-то говорят о том, кто пользователь. Но более того, эти утверждения не зависят от контекста. Они всегда верны. Ваше имя везде одинаково, как и ваш день рождения и т. Д. Используйте таблицу IdentityResource для определения областей, например, openid, профиль, электронная почта.

Заявки в маркере доступа зависят от контекста. Потому что только API знает, что означает претензия. Используйте типы пространства имен для различения утверждений.

Неважно, как настроен ресурс Api, просто помните, что при запросе области все заявки из ресурса (включая другие области в этом ресурсе) добавляются в фильтр запросов, тогда как когда область действия В запросе только заявки для этой области добавляются в фильтр запросов. Фильтр запросов, который используется для добавления всех соответствующих утверждений пользователя в токен.

Итак, теперь у вас есть токен доступа. Маркер должен содержать информацию об областях. Зачем? Потому что вы не хотите, чтобы клиенты получали доступ к недопустимым ресурсам. Ограничьте доступ, определив области для каждого клиента. Поскольку область действия - это часть функциональности, вы знаете, какие области нужны клиенту. В IdentityServer вы настраиваете те же области, чтобы соответствовать клиенту. Никогда не доверяй клиенту.

Маркер доступа содержит все заявки из запрошенной области / ресурсов. Это означает, что с этим токеном все API-интерфейсы в пределах ресурса / области могут быть доступны с этим токеном без необходимости получения нового токена для API.

Это также означает, что токен может стать довольно большим. Что-то, что вы должны избегать, прежде чем выходить за пределы. Вот почему вы не хотите разрешений в токене. Если вам нужны разрешения, то внедрите свой собственный сервер авторизации.

С другой стороны, вам нужны разрешения? Учитывая дизайн, в котором Api (ресурс) знает, к чему пользователю разрешен доступ, используйте политики (своего рода бизнес-правила) и авторизацию на основе ресурсов. Вы можете реализовать локальную пользовательскую таблицу, которая содержит информацию о разрешениях.

Кроме того, вам действительно нужны разрешения CRUD для каждого объекта? С помощью политик у вас есть возможность определить более сложную авторизацию, чем просто сравнение строковых значений.

Что касается пользователя, пользователь является ресурсом для идентификации. Но ничего не знает о границах. Таким образом, вы не можете привязать области к пользователям. У клиента есть области, которые открывают дверь для API, но API решает, имеет ли пользователь на самом деле доступ.


А теперь ответим на ваши вопросы:

a) Все заявки от пользователя, которые соответствуют запрошенным типам заявок, добавляются в токен доступа. Где запрашиваемые типы претензий берутся из запрошенных областей. Где добавляются все типы заявок ApiResource, которые связаны с запрошенными областями, и сами типы заявок запрошенных областей.

Если для API требуется информация о пользователе, он может использовать токен доступа для вызова конечной точки UserInfo. Маркер идентификации по умолчанию содержит только утверждение sub (что пользователь не может отрицать или отозвать).

b) Токены запрашиваются путем добавления областей к клиенту. По умолчанию добавляются открытые области видимости профиля. Учетные данные клиента не получат токен идентификации, и есть еще один токен - токен обновления. Обратите внимание, что этот токен доступен не всем потокам. Чтобы запросить токен обновления, добавьте область действия offline_access. Где можно взять офлайн доступ буквально. Это токен, который позволяет клиенту запрашивать новые токены доступа, не требуя ввода данных пользователем. Таким образом, в случае, если пользователь не в сети, служба может продолжить работу.

Когда требуется согласие пользователя, возможно, что определенная информация или опции недоступны. Например. если пользователь не хочет автономного доступа, то служба (например, некоторая служба синхронизации) не сможет работать. Это также происходит, когда пользователь отзывает данное согласие. Запрос нового токена доступа приведет к неавторизованному ответу.

Чтобы обойти пропущенную информацию о пользователе, просто спросите у пользователя информацию и сохраните ее локально. Вам, скорее всего, понадобится там все равно.

в) Забудьте разрешения, используйте политики и авторизацию на основе ресурсов. Реализуйте это в API. Это место, где точный контекст известен. Клиент может открыть дверь для API, но это зависит от пользователя (утверждения, информация о локальной авторизации), если ресурс может быть доступен.

Предположим, у вас есть ресурс 'weather' и области 'weather.api.full_access' и 'weather.api.read_only' (как часть ресурса 'weather').

Обратите внимание, что имя'weather.api.full_access' ничего не говорит об уровне доступа, только об ожидаемой функциональности.

Фактический уровень доступа должен основываться на локальной информации из ресурса или политик, например, у пользователя естьчитать подписку или роль администратора.

Чтобы предоставить Билли полный доступ, добавьте претензию http://api/admin (значение: true) к Билли.А для Jhon добавьте запись в таблицу подписок.

Чтобы разделить ресурс на несколько API-интерфейсов (для каждой области), используйте события для проверки области.Вы не хотите, чтобы клиент получал доступ к функциональности full_access, когда запрашивалась только область чтения.

Надеюсь, это имеет смысл для вас.Трудно дать короткий и полный ответ.Дайте мне знать, если у вас есть вопросы об этом ответе.

Короче говоря, IdentityServer может реализовать все это.Если вам нужны разрешения, взгляните на сервер политики.

0 голосов
/ 02 января 2019

a) Когда вы отправляете access_token защищенному API, почему или когда (например) ему понадобится получить некоторые утверждения о пользователе, которому он принадлежит? Может быть, если защищенный API хочет использовать некоторые данные об аутентифицированном пользователе?

Например, если ваши пользователи могут быть подразделены на организации или отделы, и вы хотите добавить политику в свой API, чтобы разрешить доступ только к определенным конечным точкам, когда пользователь входит в одну из этих подразделенных групп - вы можете добавить пользовательский заявка "organisationid" или "departmentid "и добавьте эту заявку с ее значением к выданным токенам. Будет ли это применимо или нет, это будет зависеть от контекста вашей проблемы, и при возникновении проблемы authorization можно ошибочно попытаться решить в authentication.

b) Для получения утверждений защищенный API должен будет связаться с конечной точкой UserEdnpoint? Он отправляет access_token? И какие утверждения содержатся в возвращенном id_token? / Что произойдет, если он запросит дополнительные утверждения о том, что пользователь имеет согласный доступ?

Вам не обязательно использовать конечную точку UserInfo. Вы можете установить для свойства клиента AlwaysIncludeUserClaimsInIdToken значение true, и все заявки будут включены в id_token по умолчанию, что устраняет необходимость в передаче туда и обратно в конечную точку UserInfo. Если вы в конечном итоге попали в оба конца, вы были правы, сказав, что вам нужно отправить access_token, представляющий пользователя, однако возвращается не id_token, а информация о пользователе. Пример из IdentityServer4 docs :

Запрос: GET / connect / userinfo Авторизация: Носитель {access_token}

Ответ: HTTP / 1.1 200 OK Тип контента: приложение / JSON { «sub»: «248289761001», "имя": "Боб Смит", "данное имя": "Боб", "family_name": "Smith", "роль": [ «Пользователь», «Админы» ]}

Наконец

Как вы указываете, какие пользователи могут получить доступ к определенным ресурсам?

Скорее всего, это следует решить с помощью Authorization, что не относится к протоколу OAuth2 или IdentityServer4. Authorization обычно обрабатывается по-разному в каждом приложении в зависимости от проблемной области. Я бы порекомендовал взглянуть на Policy Server создателей Identity Server. У них есть отличное видео, где они углубляются в эту тему, и у них также есть продукт для решения этой проблемы.

...