Поделиться через


Настройка утверждений, выданных в веб-токене JSON (JWT) для корпоративных приложений

Платформа удостоверений Майкрософт поддерживает единый вход (SSO) с большинством предварительно интегрированных приложений в коллекции приложений Microsoft Entra и пользовательских приложениях. Когда пользователь проходит проверку подлинности в приложении через платформа удостоверений Майкрософт с помощью протокола OIDC, он отправляет маркер приложению. Приложение проверяет и использует маркер для входа пользователя вместо запроса имени пользователя и пароля.

Эти веб-токены JSON (JWT), используемые приложениями OIDC и OAuth, содержат фрагменты сведений о пользователе, известном как утверждения. Утверждение представляет собой информацию, предложенную поставщиком удостоверений, о пользователе в составе токена, выпущенного для этого пользователя. В ответе OIDC данные утверждений обычно содержатся в маркере идентификатора, выданном поставщиком удостоверений в виде JWT.

Просмотр или изменение утверждений

Совет

Действия, описанные в этой статье, могут немного отличаться на портале, с который вы начинаете работу.

Чтобы просмотреть или изменить утверждения, выданные в JWT в приложении, выполните следующие действия:

  1. Войдите в Центр администрирования Microsoft Entra как минимум администратор облачных приложений.
  2. Перейдите к приложениям>Identity>Application Enterprise Для всех приложений.>
  3. Выберите приложение, выберите единый вход в меню слева и выберите пункт "Изменить " в разделе "Атрибуты и утверждения ".

Приложению может потребоваться настройка утверждений по различным причинам. Например, если приложению требуется другой набор URI утверждений или значения утверждений. С помощью раздела "Атрибуты и утверждения" можно добавить или удалить утверждение для приложения. Вы также можете создать пользовательское утверждение, конкретное для приложения на основе варианта использования.

Ниже описано, как назначить константное значение:

  1. Выберите утверждение, которое требуется изменить.
  2. Введите константное значение без кавычки в атрибуте Source в рамках вашей организации, а затем нажмите кнопку "Сохранить".

В обзоре атрибутов отображается постоянное значение.

Специальные преобразования утверждений

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

Function Description
ExtractMailPrefix() Удаляет суффикс домена из адреса электронной почты или имени участника-пользователя. Эта функция извлекает только первую часть имени пользователя. Например, joe_smith вместо joe_smith@contoso.com.
ToLower() Преобразует символы выбранного атрибута в символы нижнего регистра.
ToUpper() Преобразует символы выбранного атрибута в символы верхнего регистра.

Добавление утверждений для конкретного приложения

Чтобы добавить утверждения для конкретного приложения, выполните следующие действия.

  1. В разделе Утверждения и атрибуты пользователя выберите Добавить новое утверждение, чтобы открыть страницу Управление утверждениями пользователя.
  2. Введите имя утверждений. Значение не обязательно следовать шаблону универсального кода ресурса (URI). Если вам нужен шаблон URI, его можно разместить в поле Пространство имен.
  3. Выберите источник, из которого утверждение будет получать свое значение. Вы можете выбрать атрибут пользователя из раскрывающегося списка "Атрибут источника" или применить преобразование к атрибуту пользователя, прежде чем передавать его в качестве утверждения.

Преобразования утверждения

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

  1. В разделе Управление утверждениями выберите в качестве источника утверждения Преобразование, чтобы открыть страницу Управление преобразованием.
  2. Выберите функцию из раскрывающегося списка преобразований. В зависимости от выбранной функции укажите параметры и константное значение для вычисления в преобразовании.
  3. Обработка источника как многозначного указывает, применяется ли преобразование ко всем значениям или только к первому. По умолчанию первый элемент в утверждении с несколькими значениями применяется к преобразованиям. Если этот флажок установлен, он гарантирует, что он применяется ко всем. Этот флажок включен только для многозначных атрибутов. Например, user.proxyaddresses.
  4. Чтобы применить несколько преобразований, нажмите кнопку "Добавить преобразование". К утверждению можно применить не более двух преобразований. Например, вы можете сначала извлечь префикс электронной почты для user.mail. Затем преобразуйте строку в верхний регистр.

Для преобразования утверждений можно использовать следующие функции.

Function Description
ExtractMailPrefix() Удаляет суффикс домена из адреса электронной почты или имени участника-пользователя. Эта функция извлекает только первую часть имени пользователя. Например, joe_smith вместо joe_smith@contoso.com.
Join() Создает новое значение путем соединения двух атрибутов. При необходимости можно использовать разделитель между двумя атрибутами. Для преобразования утверждения NameID функция Join() выполняется особым образом, если вход преобразования содержит домен. Он удаляет часть домена из входных данных перед присоединением к нему с разделителем и выбранным параметром. Например, если входные данные преобразования и joe_smith@contoso.com разделитель, и параметр имеет @ значение fabrikam.com, это сочетание входных данных приводит к joe_smith@fabrikam.comвозникновению.
ToLowerCase Преобразует символы выбранного атрибута в символы нижнего регистра.
ToUpperCase Преобразует символы выбранного атрибута в символы верхнего регистра.
Contains() Выводит атрибут или константу, если входные данные соответствуют указанному значению. В противном случае можно указать другой результат, если совпадения нет.
Например, если вы хотите выпустить утверждение, в котором значение является адресом электронной почты пользователя, если он содержит домен @contoso.com, в противном случае вы хотите вывести имя участника-пользователя. Чтобы выполнить эту функцию, настройте следующие значения:
Параметр 1 (входные данные): user.email
Значение: "@contoso.com"
Параметр 2 (выходные данные): user.email
Параметр 3 (выходные данные при отсутствии совпадений): user.userprincipalname
EndWith() Выводит атрибут или константу, если входные данные заканчиваются указанным значением. В противном случае можно указать другой результат, если совпадения нет.
Например, если требуется выпустить утверждение, в котором значение является идентификатором сотрудника пользователя, если идентификатор сотрудника заканчивается 000, в противном случае вы хотите вывести атрибут расширения. Чтобы выполнить эту функцию, настройте следующие значения:
Параметр 1 (входные данные): user.employeeid
Значение: "000"
Параметр 2 (выходные данные): user.employeeid
Параметр 3 (выходные данные при отсутствии совпадений): user.extensionattribute1
StartWith() Выводит атрибут или константу, если входные данные начинаются указанным значением. В противном случае можно указать другой результат, если совпадения нет.
Например, если вы хотите вывести утверждение, в котором значение является идентификатором сотрудника пользователя, если страна или регион начинается с US, в противном случае вы хотите вывести атрибут расширения. Чтобы выполнить эту функцию, настройте следующие значения:
Параметр 1 (входные данные): user.country
Значение: "US"
Параметр 2 (выходные данные): user.employeeid
Параметр 3 (выходные данные при отсутствии совпадений): user.extensionattribute1
Extract() — после сопоставления Возвращает подстроку после ее сопоставления с указанным значением.
Например, если значение Finance_BSimonвходных данных равно, совпадающее значение равно Finance_, то выходные данные утверждения имеют значение BSimon.
Extract() — до сопоставления Возвращает подстроку до ее сопоставления с указанным значением.
Например, если значение BSimon_USвходных данных равно, совпадающее значение равно _US, то выходные данные утверждения имеют значение BSimon.
Extract() — между сопоставлениями Возвращает подстроку до ее сопоставления с указанным значением.
Например, если значение входных данных Finance_BSimon_USимеет значение, первое соответствующее значение имеет Finance__USзначение, а второй — это значение, то выходные данные утверждения .BSimon
ExtractAlpha() — префикс Возвращает буквенный префикс строки.
Например, если значение входных данных равно BSimon_123, возвращается BSimon.
ExtractAlpha() — суффикс Возвращает буквенный суффикс строки.
Например, если значение входных данных равно 123_Simon, возвращается Simon.
ExtractNumeric() — префикс Возвращает числовой префикс строки.
Например, если значение входных данных равно 123_BSimon, возвращается 123.
ExtractNumeric() — суффикс Возвращает числовой суффикс строки.
Например, если значение входных данных равно BSimon_123, возвращается 123.
IfEmpty() Выводит атрибут или константу, если входные данные пусты или имеют значение NULL.
Например, если вы хотите вывести атрибут, хранящийся в атрибуте расширения, если идентификатор сотрудника для данного пользователя пуст. Чтобы выполнить эту функцию, настройте следующие значения:
Параметр 1 (входные данные): user.employeeid
Параметр 2 (выходные данные): user.extensionattribute1
Параметр 3 (выходные данные при отсутствии совпадений): user.employeeid
IfNotEmpty() Выводит атрибут или константу, если входные данные не пустые или не имеют значение NULL.
Например, если вы хотите вывести атрибут, хранящийся в атрибуте расширения, если идентификатор сотрудника для данного пользователя не пуст. Чтобы выполнить эту функцию, настройте следующие значения:
Параметр 1 (входные данные): user.employeeid
Параметр 2 (выходные данные): user.extensionattribute1
Подстрока() — фиксированная длина Извлекает части типа строкового утверждения, начиная с символа в указанной позиции, и возвращает указанное число символов.
SourceClaim — источник утверждения преобразования, который должен выполняться.
StartIndex — отсчитываемая от нуля позиция первого знака подстроки в данном экземпляре.
Length — длина подстроки в символах.
Например:
sourceClaim — Пожалуйста,ExtractThisNow
StartIndex - 6
Длина — 11
Выходные данные: ExtractThis
Подстрока() — EndOfString Извлекает части типа строкового утверждения, начиная с символа в указанной позиции, и возвращает оставшуюся часть утверждения, начиная с указанного начального индекса.
SourceClaim — источник утверждения преобразования.
StartIndex — отсчитываемая от нуля позиция первого знака подстроки в данном экземпляре.
Например:
sourceClaim — Пожалуйста,ExtractThisNow
StartIndex - 6
Выходные данные: ExtractThisNow
RegexReplace() Преобразование RegexReplace() принимает в качестве входных параметров:
— "Параметр 1": атрибут пользователя в качестве входных данных регулярного выражения.
— Вариант доверия источнику как источнику с несколькими значениями.
— Шаблон регулярного выражения.
— Шаблон замены. Шаблон замены может содержать статический текстовый формат, а также ссылку, указывающую на регулярные выходные группы и дополнительные входные параметры.

Если вам нужны другие преобразования, отправьте свою идею на форуме отзывов в идентификаторе Microsoft Entra в категории приложения SaaS.

Преобразование утверждений на основе регулярных выражений

На следующем рисунке показан пример первого уровня преобразования:

Снимок экрана: первый уровень преобразования.

В следующей таблице приведены сведения о первом уровне преобразований. Действия, перечисленные в таблице, соответствуют меткам на предыдущем изображении. Выберите "Изменить", чтобы открыть колонку преобразования утверждений.

Действие Поле Description
1 Transformation Выберите параметр RegexReplace() в параметрах преобразования, чтобы использовать метод преобразования утверждений на основе регулярных выражений для преобразования утверждений.
2 Parameter 1 Входные данные для преобразования регулярных выражений. Например, user.mail с адресом электронной почты пользователя, например admin@fabrikam.com.
3 Treat source as multivalued Некоторые атрибуты входных данных пользователя могут быть атрибутами пользователя с несколькими значениями. Если выбранный атрибут пользователя поддерживает несколько значений, и пользователь хочет использовать несколько значений для преобразования, им необходимо выбрать источник как многозначный. Если выбрано, все значения используются для соответствия регулярных выражений, в противном случае используется только первое значение.
4 Regex pattern Регулярное выражение, вычисляемое по значению атрибута пользователя, выбранного в качестве параметра 1. Например, регулярное выражение для извлечения псевдонима пользователя из адреса электронной почты пользователя представляется как (?'domain'^.*?)(?i)(\@fabrikam\.com)$.
5 Add additional parameter Для преобразования можно использовать несколько атрибутов пользователя. Затем значения атрибутов будут объединены с выходными данными преобразования regex. Поддерживаются до пяти дополнительных параметров.
6 Replacement pattern Шаблон замены — это текстовый шаблон, содержащий заполнители для результата регулярных выражений. Все имена групп должны быть заключены в фигурные скобки, например {group-name}. Предположим, что администрация хочет использовать псевдоним пользователя с другим доменным именем, например xyz.com с именем страны слияния. В этом случае шаблон замены будет {country}.{domain}@xyz.comиметь {country} значение входного параметра и {domain} является результатом групповой оценки регулярных выражений. В таком случае ожидаемый результат .US.swmal@xyz.com

На следующем рисунке показан пример второго уровня преобразования:

Снимок экрана: второй уровень преобразования утверждений.

В следующей таблице приведены сведения о втором уровне преобразований. Действия, перечисленные в таблице, соответствуют меткам на предыдущем изображении.

Действие Поле Description
1 Transformation Преобразования утверждений на основе регулярных выражений не ограничиваются первым преобразованием и могут использоваться в качестве преобразования второго уровня. В качестве первого преобразования можно использовать любой другой метод преобразования.
2 Parameter 1 Если regexReplace() выбран в качестве преобразования второго уровня, выходные данные преобразования первого уровня используются в качестве входных данных для преобразования второго уровня. Чтобы применить преобразование, выражение regex второго уровня должно соответствовать выходным данным первого преобразования.
3 Regex pattern Шаблон regex — это регулярное выражение для преобразования второго уровня.
4 Parameter input Входные данные атрибута пользователя для преобразований второго уровня.
5 Parameter input Администраторы могут удалить выбранный входной параметр, если он больше не нужен.
6 Replacement pattern Шаблон замены — это текстовый шаблон, содержащий заполнители для имени группы результатов regex, имени входных параметров и статического текстового значения. Все имена групп должны быть заключены в фигурные скобки, такие как {group-name}. Предположим, что администрация хочет использовать псевдоним пользователя с другим доменным именем, например xyz.com с именем страны слияния. В этом случае шаблон замены будет {country}.{domain}@xyz.comиметь {country} значение входного параметра и {domain} является результатом групповой оценки регулярных выражений. В таком случае ожидаемый результат .US.swmal@xyz.com
7 Test transformation Преобразование RegexReplace() вычисляется только в том случае, если значение выбранного пользовательского атрибута для параметра 1 соответствует регулярному выражению, предоставленному в текстовом поле шаблона Regex. Если они не совпадают, значение утверждения по умолчанию добавляется в маркер. Для проверки регулярного выражения на соответствие значению входного параметра в колонке преобразования доступен тестовый интерфейс. Этот тестовый интерфейс работает только с фиктивными значениями. При использовании дополнительных входных параметров имя параметра добавляется в результат теста вместо фактического значения. Чтобы получить доступ к разделу теста, выберите "Тестирование преобразования".

На следующем рисунке показан пример тестирования преобразований:

Снимок экрана: тестирование преобразования.

В следующей таблице приведены сведения о тестировании преобразований. Действия, перечисленные в таблице, соответствуют меткам на предыдущем изображении.

Действие Поле Description
1 Test transformation Нажмите кнопку закрытия или (X), чтобы скрыть раздел теста и снова отобразить кнопку преобразования "Тест" в колонке.
2 Test regex input Принимает входные данные, используемые для оценки теста регулярного выражения. Если преобразование утверждений на основе регулярных выражений настроено как преобразование второго уровня, укажите значение, которое является ожидаемым результатом первого преобразования.
3 Run test После предоставления входных данных тестового регулярного выражения и настройки шаблона regex, шаблона замены и входных параметров выражение можно оценить, выбрав команду "Выполнить тест".
4 Test transformation result Если оценка выполнена успешно, выходные данные преобразования теста отрисовывается в метку результата преобразования теста.
5 Remove transformation Преобразование второго уровня можно удалить, выбрав "Удалить преобразование".
6 Specify output if no match Если входное значение регулярного выражения настроено для параметра 1 , который не соответствует регулярному выражению, преобразование пропускается. В таких случаях можно настроить альтернативный атрибут пользователя, который добавляется в маркер утверждения, проверяя выходные данные, если совпадения не совпадают.
7 Parameter 3 Если альтернативный атрибут пользователя должен быть возвращен, если нет совпадения и указать выходные данные, если совпадения не установлен, можно выбрать альтернативный атрибут пользователя с помощью раскрывающегося списка. Этот раскрывающийся список доступен для параметра 3 (выходные данные, если совпадения не совпадают).
8 Summary В нижней части колонки отображается полная сводка формата, объясняющая смысл преобразования в простом тексте.
9 Add После проверки параметров конфигурации для преобразования его можно сохранить в политике утверждений, нажав кнопку "Добавить". Нажмите кнопку "Сохранить " в колонке "Управление утверждениями" , чтобы сохранить изменения.

Преобразование RegexReplace() также доступно для преобразований утверждений группы.

Проверки преобразования

В сообщении содержатся дополнительные сведения о следующих условиях после нажатия кнопки "Добавить " или "Выполнить тест".

  • Использовались входные параметры с повторяющимися атрибутами пользователя.
  • Неиспользуемые входные параметры найдены. Определенные входные параметры должны соответствующим образом использоваться в тексте шаблона замены.
  • Предоставленные входные данные регулярного выражения теста не соответствуют предоставленному регулярному выражению.
  • Источники для групп в шаблоне замены не найдены.

Выдача утверждений на основе условий

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

Ниже перечислены возможные типы пользователя.

  • Все пользователи могут получить доступ к приложению.
  • Члены: собственный член клиента
  • Все гости: пользователь переехал из внешней организации с идентификатором Microsoft Entra или без нее.
  • Гости Microsoft Entra: гостевой пользователь принадлежит другой организации с помощью идентификатора Microsoft Entra.
  • Внешние гости: гостевой пользователь принадлежит внешней организации, у которой нет идентификатора Microsoft Entra.

Один из сценариев, когда тип пользователя является полезным, если источник утверждения отличается для гостя и сотрудника, обращающегося к приложению. Можно указать, что если пользователь является сотрудником, получите идентификатор NameID из user.email. Если пользователь является гостем, идентификатор NameID поступает из user.extensionattribute1.

Чтобы добавить условие утверждения, выполните следующие действия.

  1. В разделе Управление утверждениями разверните условия утверждения.
  2. Выберите тип пользователя.
  3. Выберите группы, к которым должен принадлежать пользователь. Для конкретного приложения можно выбрать до 50 уникальных групп во всех утверждениях.
  4. Выберите источник, из которого утверждение будет получать свое значение. Вы можете выбрать атрибут пользователя из раскрывающегося списка "Атрибут источника" или применить преобразование к атрибуту пользователя, прежде чем передавать его в качестве утверждения.

Порядок добавления условий важен. Microsoft Entra сначала вычисляет все условия с исходным кодом, а затем оценивает все условия с источником Attribute Transformation , чтобы решить, какое значение следует вывести в утверждении. Идентификатор Microsoft Entra оценивает условия с тем же источником сверху вниз. Утверждение выдает последнее значение, соответствующее выражению в утверждении. Такие преобразования, как IsNotEmpty и Contains действуют как ограничения.

Например, Britta Simon является гостевым пользователем в клиенте Contoso. Britta принадлежит другой организации, которая также использует идентификатор Microsoft Entra. Учитывая следующую конфигурацию для приложения Fabrikam, когда Britta пытается войти в Fabrikam, платформа удостоверений Майкрософт оценивает условия.

Во-первых, платформа удостоверений Майкрософт проверяет, является ли тип пользователя Britta всеми гостями. Поскольку тип — "Все гости", платформа удостоверений Майкрософт назначает источник утвержденияuser.extensionattribute1. Во-вторых, платформа удостоверений Майкрософт проверяет, является ли тип пользователя Britta гостями Microsoft Entra. Поскольку тип — "Все гости", платформа удостоверений Майкрософт назначает источник утвержденияuser.mail. Наконец, утверждение создается со значением user.mail britta.

В качестве другого примера рассмотрим, когда Britta Simon пытается войти с помощью следующей конфигурации. Microsoft Entra сначала оценивает все условия с исходным кодом Attribute. Источником утверждения является user.mail тип пользователя Britta— гости Microsoft Entra. Затем идентификатор Microsoft Entra оценивает преобразования. Так как Britta является гостем, user.extensionattribute1 является новым источником для утверждения. Так как Britta находится в гостях Microsoft Entra, user.othermail это новый источник для этого утверждения. Наконец, утверждение создается со значением user.othermail britta.

В последнем примере рассмотрим, что происходит, если Britta не user.othermail настроена или пуста. Утверждение возвращается к user.extensionattribute1 игнорированию записи условия в обоих случаях.

Вопросы безопасности

Приложения, получающие маркеры, полагаются на значения утверждений, которые не могут быть изменены. При изменении содержимого маркера с помощью настройки утверждений эти предположения больше не могут быть правильными. Приложения должны явно подтвердить, что маркеры были изменены, чтобы защитить себя от настроек, созданных вредоносными субъектами. Защита от неуместных настроек одним из следующих способов:

Без этого идентификатор Microsoft Entra возвращает код ошибки AADSTS50146.

Настройка пользовательского ключа подписывания

Для мультитенантных приложений следует использовать пользовательский ключ подписи. Не устанавливайте acceptMappedClaims в манифесте приложения. При настройке приложения в портал Azure вы получите объект регистрации приложения и субъект-службу в клиенте. Это приложение использует ключ глобального входа Azure, который не может использоваться для настройки утверждений в токенах. Чтобы поместить настраиваемые утверждения в маркеры, создайте пользовательский ключ входа на основе сертификата и добавьте его в субъект-службу. В целях тестирования можно создать самозаверяющий сертификат. После настройки пользовательского ключа подписи код приложения должен проверить ключ подписи маркера.

Добавьте следующие сведения в субъект-службу.

Извлеките закрытый и открытый ключи в кодировке base-64 из экспортированного PFX-файла сертификата. Убедитесь, что keyId для keyCredential, который используется для подписывания (Sign), совпадает с keyId для passwordCredential. Вы можете создать customkeyIdentifier, получив хэш отпечатка сертификата.

Запросить

Примечание.

Сначала отключите любую конфигурацию блокировки субъекта-службы для только что созданных приложений из колонки регистрации приложений Центра администрирования Microsoft Entra, прежде чем пытаться выполнить исправление для субъекта-службы, что приведет к 400 плохим запросам.

В следующем примере показан формат HTTP-запроса PATCH для добавления пользовательского ключа подписи в субъект-службу. Значение key в свойстве keyCredentials сокращено для удобства чтения. Это значение предоставляется в кодировке base-64. Для закрытого ключа используется Signсвойство. Для открытого ключа используется Verifyсвойство.

PATCH https://graph.microsoft.com/v1.0/servicePrincipals/aaaaaaaa-bbbb-cccc-1111-222222222222

Content-type: servicePrincipals/json
Authorization: Bearer {token}

{
    "keyCredentials":[
        {
            "customKeyIdentifier": "aB1cD2eF3gH4iJ5kL6-mN7oP8qR=", 
            "endDateTime": "2021-04-22T22:10:13Z",
            "keyId": "aaaaaaaa-0b0b-1c1c-2d2d-333333333333",
            "startDateTime": "2020-04-22T21:50:13Z",
            "type": "X509CertAndPassword",
            "usage": "Sign",
            "key":"cD2eF3gH4iJ5kL6mN7-oP8qR9sT==",
            "displayName": "CN=contoso"
        },
        {
            "customKeyIdentifier": "aB1cD2eF3gH4iJ5kL6-mN7oP8qR=",
            "endDateTime": "2021-04-22T22:10:13Z",
            "keyId": "bbbbbbbb-1c1c-2d2d-3e3e-444444444444",
            "startDateTime": "2020-04-22T21:50:13Z",
            "type": "AsymmetricX509Cert",
            "usage": "Verify",
            "key": "cD2eF3gH4iJ5kL6mN7-oP8qR9sT==",
            "displayName": "CN=contoso"
        }

    ],
    "passwordCredentials": [
        {
            "customKeyIdentifier": "aB1cD2eF3gH4iJ5kL6-mN7oP8qR=",
            "keyId": "cccccccc-2d2d-3e3e-4f4f-555555555555",
            "endDateTime": "2022-01-27T19:40:33Z",
            "startDateTime": "2020-04-20T19:40:33Z",
            "secretText": "mypassword"
        }
    ]
}

Настройка пользовательского ключа подписывания с помощью PowerShell

С помощью PowerShell создайте экземпляр общедоступного клиентского приложения MSAL и примените поток предоставления кода авторизации, чтобы получить маркер доступа с делегированными привилегиями для Microsoft Graph. Примените этот маркер доступа для вызова Microsoft Graph и настройки пользовательского ключа подписывания для субъекта-службы. После настройки пользовательского ключа подписи код приложения должен проверить ключ подписи маркера.

Чтобы запустить этот скрипт, вам потребуется:

  • Идентификатор объекта субъекта-службы приложения, который находится в колонке "Обзор" записи приложения в корпоративных приложениях в портал Azure.
  • Регистрация приложения для выполнения входа пользователя и получения маркера доступа для вызова Microsoft Graph. Идентификатор приложения (клиента), который можно получить в области Обзор для этого приложения в разделе Регистрация приложений на портале Azure. Регистрация приложения должна иметь следующую конфигурацию:
    • Универсальный код ресурса (URI перенаправления) "http://localhost" указана в конфигурации платформы мобильных и классических приложений .
    • В разрешениях API делегированные разрешения Microsoft Graph Application.ReadWrite.All и User.Read (убедитесь, что вы предоставляете согласие администратора этим разрешениям).
  • Пользователь, который входит в систему для получения маркера доступа Microsoft Graph. Пользователь должен быть одной из следующих административных ролей Microsoft Entra (требуется для обновления субъекта-службы):
    • Администратор облачных приложений
    • Администратор приложений
  • Сертификат для использования в качестве пользовательского ключа подписывания в приложении. Вы можете создать самозаверяющий сертификат или получить сертификат в любом доверенном центре сертификации. В скрипте используются следующие компоненты сертификата:
    • открытый ключ (обычно файл .cer )
    • закрытый ключ в формате PKCS#12 (в PFX-файле )
    • пароль для закрытого ключа (PFX-файл )

Внимание

Закрытый ключ должен быть в формате PKCS#12, так как идентификатор Microsoft Entra id не поддерживает другие типы форматов. Использование неправильного формата может привести к ошибке "Недопустимый сертификат: значение ключа является недопустимым сертификатом" при использовании Microsoft Graph для исправления субъекта-службы с keyCredentials информацией о сертификате.

##########################################################
# Replace the variables below with the appropriate values 

$fqdn="yourDomainHere" # This is used for the 'issued to' and 'issued by' field of the certificate
$pwd="password" # password for exporting the certificate private key
$tenantId   = "aaaabbbb-0000-cccc-1111-dddd2222eeee" # Replace with your Tenant ID
$appObjId = "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb" # Replace with the Object ID of the App Registration

##########################################################

# Create a self-signed cert

$cert = New-SelfSignedCertificate -certstorelocation cert:\currentuser\my -DnsName $fqdn
$pwdSecure = ConvertTo-SecureString -String $pwd -Force -AsPlainText
$path = 'cert:\currentuser\my\' + $cert.Thumbprint
$location="C:\\temp" # path to folder where both the pfx and cer file will be written to
$cerFile = $location + "\\" + $fqdn + ".cer"
$pfxFile = $location + "\\" + $fqdn + ".pfx"
 
# Export the public and private keys
Export-PfxCertificate -cert $path -FilePath $pfxFile -Password $pwdSecure
Export-Certificate -cert $path -FilePath $cerFile

$pfxpath = $pfxFile # path to pfx file
$cerpath = $cerFile # path to cer file
$password = $pwd  # password for the pfx file
 
# Check PowerShell version (minimum 5.1) (.Net) or PowerShell Core (.Net Core) and read the certificate file accordingly
 
if ($PSVersionTable.PSVersion.Major -gt 5)
    { 
        $core = $true
    }
else
    { 
        $core = $false
    }
 
    #  this is for PowerShell Core
    $Secure_String_Pwd = ConvertTo-SecureString $password -AsPlainText -Force
 
    # reading certificate files and creating Certificate Object
    if ($core)
    {
        $pfx_cert = get-content $pfxpath -AsByteStream -Raw
        $cer_cert = get-content $cerpath -AsByteStream -Raw
        $cert = Get-PfxCertificate -FilePath $pfxpath -Password $Secure_String_Pwd
    }
    else
    {
        $pfx_cert = get-content $pfxpath -Encoding Byte
        $cer_cert = get-content $cerpath -Encoding Byte
        # calling Get-PfxCertificate in PowerShell 5.1 prompts for password - using alternative method
        $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($pfxpath, $password)
    }

 
    # base 64 encode the private key and public key
    $base64pfx = [System.Convert]::ToBase64String($pfx_cert)
    $base64cer = [System.Convert]::ToBase64String($cer_cert)
 
    # getting id for the keyCredential object
    $guid1 = New-Guid
    $guid2 = New-Guid
 
    # get the custom key identifier from the certificate thumbprint:
    $hasher = [System.Security.Cryptography.HashAlgorithm]::Create('sha256')
    $hash = $hasher.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($cert.Thumbprint))
    $customKeyIdentifier = [System.Convert]::ToBase64String($hash)
 
    # get end date and start date for our keycredentials
    $endDateTime = ($cert.NotAfter).ToUniversalTime().ToString( "yyyy-MM-ddTHH:mm:ssZ" )
    $startDateTime = ($cert.NotBefore).ToUniversalTime().ToString( "yyyy-MM-ddTHH:mm:ssZ" )
 
    # building our json payload
    $object = [ordered]@{    
    keyCredentials = @(       
         [ordered]@{            
            customKeyIdentifier = $customKeyIdentifier
            endDateTime = $endDateTime
            keyId = $guid1
            startDateTime = $startDateTime 
            type = "AsymmetricX509Cert"
            usage = "Sign"
            key = $base64pfx
            displayName = "CN=$fqdn" 
        },
        [ordered]@{            
            customKeyIdentifier = $customKeyIdentifier
            endDateTime = $endDateTime
            keyId = $guid2
            startDateTime = $startDateTime 
            type = "AsymmetricX509Cert"
            usage = "Verify"
            key = $base64cer
            displayName = "CN=$fqdn"   
        }
        )  
    passwordCredentials = @(
        [ordered]@{
            customKeyIdentifier = $customKeyIdentifier
            displayName = "CN=$fqdn"
            keyId = $guid1           
            endDateTime = $endDateTime
            startDateTime = $startDateTime
            secretText = $password
            hint = $null
        }
    )
    }
 
Connect-MgGraph -tenantId $tenantId -Scopes Application.ReadWrite.All
$graphuri = "https://graph.microsoft.com/v1.0/applications/$appObjId"
Invoke-MgGraphRequest -Method PATCH -Uri $graphuri -Body $object

    $json = $object | ConvertTo-Json -Depth 99
    Write-Host "JSON Payload:"
    Write-Output $json

Проверка ключа подписывания маркера

Приложения с включенным сопоставлением утверждений должны проверять ключи подписывания маркеров, добавляя appid={client_id} к их запросам метаданных. В следующем примере показан формат документа метаданных OpenID Connect, который следует использовать:

https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration?appid={client-id}

Обновление манифеста приложения

Для приложений с одним арендатором можно задать для свойства acceptMappedClaims значение true в манифесте приложения. Как описано в типе apiApplicationресурса. Задание свойства позволяет приложению использовать сопоставление утверждений без указания пользовательского ключа подписи.

Предупреждение

Не устанавливайте свойство acceptMappedClaims значение true для мультитенантных приложений, что позволяет злоумышленникам создавать политики сопоставления утверждений для приложения.

Запрашиваемая аудитория маркеров необходима для использования проверенного доменного имени клиента Microsoft Entra, что означает, что необходимо задать Application ID URI (представленный identifierUris в манифесте приложения), например https://contoso.com/my-api или (просто используя имя клиента по умолчанию). https://contoso.onmicrosoft.com/my-api

Если вы не используете проверенный домен, идентификатор Microsoft Entra возвращает AADSTS501461 код ошибки с сообщением "_AcceptMappedClaims поддерживается только для аудитории маркеров, соответствующей GUID приложения или аудитории в проверенных доменах клиента. Измените идентификатор ресурса или используйте ключ подписи для конкретного приложения".

Дополнительные параметры утверждений

Настройте расширенные параметры утверждений для приложений OIDC, чтобы предоставить то же утверждение, что и токены SAML. Кроме того, для приложений, которые намерены использовать одно и то же утверждение для токенов ответа SAML2.0 и OIDC.

Настройте расширенные параметры утверждения, установив флажок в разделе "Дополнительные параметры утверждений" в колонке "Управление утверждениями ".