поток неявного предоставления платформа удостоверений Майкрософт и OAuth 2.0
Платформа удостоверений Майкрософт поддерживает поток неявного предоставления OAuth 2.0, как описано в спецификации OAuth 2.0. Определяющая особенность неявного предоставления заключается в том, что маркеры (маркеры идентификатора или маркеры доступа) возвращаются непосредственно из конечной точки /authorize вместо конечной точки /token. Это часто используется как часть потока кода авторизации, в том, что называется "гибридным потоком" — получение маркера идентификатора в запросе /authorization вместе с кодом авторизации.
В этой статье описывается, как напрямую программировать протокол в приложении для запроса маркеров из идентификатора Microsoft Entra. По возможности рекомендуется использовать поддерживаемые библиотеки проверки подлинности Майкрософт (MSAL) вместо получения маркеров и вызова защищенных веб-API. Список примеров кода, использующих MSAL, см. в платформа удостоверений Майкрософт примерах кода.
Предупреждение
Корпорация Майкрософт рекомендует не использовать неявный поток предоставления. В большинстве случаев более безопасные альтернативные варианты доступны и рекомендуется. Для определенных конфигураций этого потока требуется очень высокий уровень доверия к приложению и риск, который не присутствует в других потоках. Этот поток следует использовать только в том случае, если другие более безопасные потоки недоступны. Дополнительные сведения см. в проблемах безопасности с неявным потоком предоставления.
Схема протокола
На следующей схеме показано, как выглядит весь поток неявного входа и разделы, которые подробно описывают каждый шаг.
Подходящие сценарии для неявного предоставления OAuth2
Неявное предоставление является надежным только для начальной интерактивной части потока входа, где отсутствие сторонних файлов cookie не влияет на ваше приложение. Это ограничение означает, что оно следует использовать исключительно в рамках гибридного потока, где приложение запрашивает код и маркер из конечной точки авторизации. В гибридном потоке приложение получает код, который можно активировать для маркера обновления, что гарантирует, что сеанс входа приложения остается действительным с течением времени.
Предпочитать поток кода проверки подлинности
При удалении поддержки сторонних файлов cookie некоторые браузеры неявный поток предоставления больше не является подходящим методом проверки подлинности. Функции автоматического единого входа в неявном потоке не работают без сторонних файлов cookie, что приводит к разрыву приложений при попытке получить новый токен. Настоятельно рекомендуется, чтобы все новые приложения использовали поток кода авторизации, который теперь поддерживает одностраничные приложения вместо неявного потока. Существующие одностраничные приложения также должны переноситься в поток кода авторизации.
Проблемы безопасности с неявным потоком предоставления
Поток неявного предоставления предназначен для традиционных веб-приложений, где сервер имеет контроль над безопасной обработкой данных POST. Существует два основных способа доставки маркеров с неявным потоком предоставления: где response_mode
возвращается в качестве фрагмента URL-адреса или в качестве параметра запроса (с помощью form POST
и GET
). В неявном потоке, где response_mode=form_post
маркер безопасно поставляется через HTML-форму POST в URI перенаправления клиента. Этот метод гарантирует, что маркер не предоставляется в фрагменте URL-адреса, что, в свою очередь, позволяет избежать рисков утечки маркеров через журнал браузера или заголовки ссылок.
Проблемы безопасности с неявным потоком возникают при доставке маркеров с помощью response_mode=fragment
. Фрагмент URL-адреса является частью URL-адреса, который поступает после символа #
и не отправляется на сервер, когда браузер запрашивает новую страницу, но доступен для JavaScript, запущенного в браузере. Это означает, что маркер предоставляется любому JavaScript, работающему на странице, что может быть угрозой безопасности, если страница включает сторонние скрипты. Эти проблемы безопасности для маркеров в spAs также не применяются к неявным потокам form POST
.
Когда следует разрешить выдачу маркера доступа или маркера идентификатора при запросе с помощью неявного предоставления или гибридного потока?
Неявный поток предоставления и гибридного потока не так безопасны, как и другие потоки OAuth. Если это не обязательно, вы не должны разрешать выдачу маркера доступа или идентификатора при запросе с использованием неявного предоставления или гибридного потока в регистрации приложения. Если вы (или разработчики) используете MSAL в приложении для реализации проверки подлинности и авторизации, то ни в коем случае не нужно включить поле.
Однако если вы (или разработчики) не используете MSAL в приложении, в следующей таблице описаны, когда маркеры доступа или маркер идентификатора должны быть включены.
Тип создаваемого приложения | Маркеры, которые необходимо включить в регистрации приложений |
---|---|
SPA (одностраничное приложение), которое не использует поток кода авторизации с PKCE | Маркеры доступа и маркеры идентификатора |
Веб-приложение или приложение SPA, которое вызывает веб-API через JavaScript с помощью неявного потока | Маркеры доступа и маркеры идентификатора |
Веб-приложение ASP.NET Core и другие веб-приложения, использующие гибридную проверку подлинности | Маркеры идентификатора |
Отправка запроса на вход
Для первоначального входа пользователя в приложение можно отправить запрос проверки подлинности OpenID Connect и получить его id_token
из платформа удостоверений Майкрософт.
Важный
Чтобы успешно запросить маркер идентификатора и (или) маркер доступа, регистрация приложения в Центре администрирования Microsoft Entra — Регистрация приложений страница должна иметь соответствующий неявный поток предоставления, выбрав маркеры идентификатора и маркеры доступа в разделе неявного предоставления и гибридных потоков. Если он не включен, unsupported_response
будет возвращена ошибка:
The provided value for the input parameter 'response_type' is not allowed for this client. Expected value is 'code'
// Line breaks for legibility only
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=00001111-aaaa-2222-bbbb-3333cccc4444
&response_type=id_token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&scope=openid
&response_mode=fragment
&state=12345
&nonce=678910
Параметр | Тип | Описание |
---|---|---|
tenant |
Обязательно | Значение {tenant} в пути запроса можно использовать для управления тем, кто может войти в приложение. Допустимые значения: common , organizations consumers и идентификаторы клиента. Дополнительные сведения см . в основах протокола. Критически важно для гостевых сценариев, когда вы подписываете пользователя из одного клиента в другой клиент, необходимо предоставить идентификатор клиента, чтобы правильно войти в клиент ресурсов. |
client_id |
Обязательно | Идентификатор приложения (клиента), который центр администрирования Microsoft Entra — Регистрация приложений страницу, назначенную вашему приложению. |
response_type |
Обязательно | Необходимо включить id_token для входа OpenID Connect. Он также может включать response_type , token . С помощью token этого приложения можно сразу получить маркер доступа из конечной точки /authorize, не выполняя второй запрос к конечной точке /authorize. Если вы используете token response_type, параметр должен содержать область, scope указывающую, какой ресурс должен выдавать маркер (например, user.read в Microsoft Graph). Он также может содержать code вместо token предоставления кода авторизации для использования в потоке кода авторизации. Этот id_token +code ответ иногда называется гибридным потоком. |
redirect_uri |
рекомендованный | URI перенаправления приложения, где ответы проверки подлинности отправляются и получаются в приложении. Он должен точно соответствовать одному из URI перенаправления, зарегистрированных в Центре администрирования Microsoft Entra, за исключением того, что он должен быть закодирован URL-адресом. |
scope |
Обязательно | Разделенный пробелами список областей. Для OpenID Connect (id_tokens ) она должна включать область openid , которая преобразуется в разрешение "Вход" в пользовательском интерфейсе согласия. Кроме того, может потребоваться включить email и profile области для получения доступа к дополнительным пользовательским данным. Вы также можете включить другие области в этот запрос для запроса согласия на различные ресурсы, если маркер доступа запрашивается. |
response_mode |
рекомендованный | Указывает метод, который следует использовать для отправки полученного маркера обратно в приложение. По умолчанию используется query только маркер доступа, но fragment если запрос включает id_token. По соображениям безопасности рекомендуется использовать form_post неявный поток, чтобы убедиться, что маркер не предоставляется в фрагменте URL-адреса. |
state |
рекомендованный | Значение, включенное в запрос, также возвращается в ответе маркера. Это может быть строка любого содержимого, которое вы хотите. Случайно созданное уникальное значение обычно используется для предотвращения атак между сайтами. Состояние также используется для кодирования сведений о состоянии пользователя в приложении до того, как произошел запрос на проверку подлинности, например страницу или представление, на которое они были подключены. |
nonce |
Обязательно | Значение, включенное в запрос, созданное приложением, которое включается в полученный маркер идентификатора в качестве утверждения. Затем приложение может проверить это значение, чтобы устранить атаки воспроизведения маркеров. Значение обычно является случайной уникальной строкой, которая может использоваться для идентификации источника запроса. Требуется только при запросе id_token. |
prompt |
необязательный | Указывает тип необходимого взаимодействия с пользователем. Единственными допустимыми значениями в данный момент являются login , none select_account и consent . prompt=login заставляет пользователя вводить свои учетные данные в этом запросе, отрицая единый вход. prompt=none является противоположностью — это гарантирует, что пользователь не представлен интерактивным запросом в любом случае. Если запрос не может быть выполнен автоматически через единый вход, платформа удостоверений Майкрософт возвращает ошибку. prompt=select_account отправляет пользователя в средство выбора учетных записей, где отображаются все учетные записи, запоминаемые в сеансе. prompt=consent активирует диалоговое окно согласия OAuth после входа пользователя, запрашивая у пользователя предоставление разрешений приложению. |
login_hint |
необязательный | Этот параметр можно использовать для предварительного заполнения поля имени пользователя и адреса электронной почты страницы входа пользователя, если вы знаете имя пользователя заранее. Часто приложения используют этот параметр во время повторной проверки подлинности после извлечения необязательного login_hint утверждения из предыдущего входа. |
domain_hint |
необязательный | Если он включен, он пропускает процесс обнаружения на основе электронной почты, который пользователь проходит на странице входа, что приводит к немного более упрощенной пользовательской среде. Этот параметр обычно используется для приложений Line of Business, работающих в одном клиенте, где они предоставляют доменное имя в данном клиенте, перенаправляя пользователя поставщику федерации для этого клиента. Это указание предотвращает вход гостей в это приложение и ограничивает использование облачных учетных данных, таких как FIDO. |
На этом этапе пользователю предлагается ввести свои учетные данные и завершить проверку подлинности. Платформа удостоверений Майкрософт гарантирует, что пользователь дал согласие на разрешения, указанные в параметре scope
запроса. Если пользователь дал согласие ни одному из этих разрешений, он просит пользователя предоставить согласие на необходимые разрешения. Дополнительные сведения см. в разделе "Разрешения", "Согласие" и "Мультитенантные приложения".
После проверки подлинности пользователя и предоставления согласия платформа удостоверений Майкрософт возвращает ответ на указанное приложениеredirect_uri
, используя метод, указанный в параметреresponse_mode
.
Успешный ответ
Успешный ответ с использованием response_mode=fragment
и response_type=id_token+code
выглядит следующим образом (с разрывами строк для удобочитаемости):
GET https://localhost/myapp/#
code=0.AgAAktYV-sfpYESnQynylW_UKZmH-C9y_G1A
&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...
&state=12345
Параметр | Описание |
---|---|
code |
Включен, если response_type включается code . Это код авторизации, подходящий для использования в потоке кода авторизации. |
access_token |
Включен, если response_type включается token . Маркер доступа, запрошенный приложением. Маркер доступа не должен быть декодирован или проверяться иным образом, он должен рассматриваться как непрозрачная строка. |
token_type |
Включен, если response_type включается token . Это всегда Bearer . |
expires_in |
Включен, если response_type включается token . Указывает количество секунд, допустимое для кэширования маркера. |
scope |
Включен, если response_type включается token . Указывает одну или несколько областей, для которых access_token допустимо. Может не включать все запрошенные области, если они не применимы к пользователю. Например, области, доступные только для Записи Майкрософт, запрашиваемые при входе в систему с помощью личная учетная запись. |
id_token |
Подписанный веб-токен JSON (JWT). Приложение может декодировать сегменты этого маркера, чтобы запросить сведения о пользователе, выполнившем вход. Приложение может кэшировать значения и отображать их, но оно не должно полагаться на них для каких-либо границ авторизации или безопасности. Дополнительные сведения о маркерах идентификаторов см. в разделе id_token reference . Примечание. Указано только в том случае, если openid область была запрошена и response_type включена id_tokens . |
state |
Если параметр состояния включен в запрос, то в ответе должно появиться то же значение. Приложение должно убедиться, что значения состояния в запросе и ответе идентичны. |
Предупреждение
Не пытайтесь проверить или прочитать маркеры для любого API, который вы не владеете, включая маркеры в этом примере в коде. Маркеры для службы Майкрософт могут использовать специальный формат, который не будет проверяться как JWT, а также может быть зашифрован для пользователей потребительских (учетных записей Майкрософт). Хотя маркеры чтения — это полезное средство отладки и обучения, не зависимые от этого в коде или предполагайте конкретные сведения о маркерах, которые не используются для управляемого API.
Ответ на ошибку
Ответы на ошибки также могут быть отправлены redirect_uri
в приложение, чтобы оно соответствующих способов их обработки:
GET https://localhost/myapp/#
error=access_denied
&error_description=the+user+canceled+the+authentication
Параметр | Описание |
---|---|
error |
Строка кода ошибки, которая может использоваться для классификации типов возникающих ошибок и может использоваться для реагирования на ошибки. |
error_description |
Определенное сообщение об ошибке, которое может помочь разработчику определить первопричину ошибки проверки подлинности. |
Автоматическое получение маркеров доступа
Теперь, когда пользователь вошел в одностраничные приложения, вы можете автоматически получать маркеры доступа для вызова веб-API, защищенных платформа удостоверений Майкрософт, таких как Microsoft Graph. Даже если вы уже получили маркер с помощью token
response_type, этот метод можно использовать для получения маркеров дополнительных ресурсов без перенаправления пользователя для повторного входа.
Важный
Эта часть неявного потока вряд ли будет работать для приложения, так как она используется в разных браузерах из-за удаления сторонних файлов cookie по умолчанию. Хотя это по-прежнему работает в браузерах на основе Chromium, которые не находятся в Incognito, разработчики должны пересмотреть использование этой части потока. В браузерах, не поддерживающих сторонние файлы cookie, вы получите сообщение об ошибке, указывающее, что пользователи не вошли в систему, так как файлы cookie сеанса страницы входа были удалены браузером.
В обычном потоке OpenID Connect/OAuth это можно сделать, выполнив запрос к конечной точке платформа удостоверений Майкрософт/token
. Запрос можно сделать в скрытом iframe, чтобы получить новые маркеры для других веб-API:
// Line breaks for legibility only
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=00001111-aaaa-2222-bbbb-3333cccc4444&response_type=token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read
&response_mode=fragment
&state=12345
&nonce=678910
&prompt=none
&login_hint=myuser@mycompany.com
Дополнительные сведения о параметрах запроса в URL-адресе см . в запросе на вход.
Кончик
Попробуйте скопировать и вставить следующий запрос на вкладку браузера с помощью реальной client_id
и username
из регистрации приложения. Это позволит увидеть автоматический запрос маркера в действии.
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id={your-client-id}&response_type=token&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F&scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read&response_mode=fragment&state=12345&nonce=678910&prompt=none&login_hint={username}
Обратите внимание, что это будет работать даже в браузерах без поддержки сторонних файлов cookie, так как вы вводите его непосредственно в панель браузера, а не открываете его в iframe.
Благодаря параметру prompt=none
этот запрос завершается успешно или завершается сбоем немедленно и возвращается в приложение. Ответ отправляется приложению по указанному адресу redirect_uri
, используя метод, указанный в параметре response_mode
.
Успешный ответ
Успешный ответ с использованием response_mode=fragment
выглядит следующим образом:
GET https://localhost/myapp/#
access_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...
&state=12345
&token_type=Bearer
&expires_in=3599
&scope=https%3A%2F%2Fgraph.microsoft.com%2Fdirectory.read
Параметр | Описание |
---|---|
access_token |
Включен, если response_type включается token . Маркер доступа, запрошенный приложением, в данном случае для Microsoft Graph. Маркер доступа не должен быть декодирован или проверяться иным образом, он должен рассматриваться как непрозрачная строка. |
token_type |
Это всегда Bearer . |
expires_in |
Указывает количество секунд, допустимое для кэширования маркера. |
scope |
Указывает одну или несколько областей, для которых допустимы маркер доступа. Может не включать все запрошенные области, если они не применимы к пользователю (если области, доступные только для Microsoft Entra, запрашиваются, когда личная учетная запись используется для входа). |
id_token |
Подписанный веб-токен JSON (JWT). Включен, если response_type включается id_token . Приложение может декодировать сегменты этого маркера, чтобы запросить сведения о пользователе, выполнившем вход. Приложение может кэшировать значения и отображать их, но оно не должно полагаться на них для каких-либо границ авторизации или безопасности. Дополнительные сведения о id_tokens см. в справочникеid_token . Примечание. Указано только в том случае, если openid область была запрошена. |
state |
Если параметр состояния включен в запрос, то в ответе должно появиться то же значение. Приложение должно убедиться, что значения состояния в запросе и ответе идентичны. |
Ответ на ошибку
Ответы об ошибках также могут быть отправлены redirect_uri
в приложение, чтобы приложение ему соответствующим образом обрабатывалось. Если prompt=none
ожидаемое сообщение об ошибке:
GET https://localhost/myapp/#
error=user_authentication_required
&error_description=the+request+could+not+be+completed+silently
Параметр | Описание |
---|---|
error |
Строка кода ошибки, которая может использоваться для классификации типов возникающих ошибок и может использоваться для реагирования на ошибки. |
error_description |
Определенное сообщение об ошибке, которое может помочь разработчику определить первопричину ошибки проверки подлинности. |
Если эта ошибка возникает в запросе iframe, пользователь должен повторно войти в систему, чтобы получить новый маркер. Этот случай можно обрабатывать любым способом.
Обновление маркеров
Неявное предоставление не предоставляет маркеры обновления. Срок действия маркеров идентификатора и маркеров доступа истекает через короткий период времени, поэтому приложение должно периодически обновлять эти маркеры. Чтобы обновить любой тип маркера, можно выполнить тот же скрытый запрос iframe ранее, используя prompt=none
параметр для управления поведением платформы удостоверений. Если вы хотите получить новый маркер идентификатора, обязательно используйте id_token
его response_type
scope=openid
и nonce
параметр.
В браузерах, не поддерживающих сторонние файлы cookie, это приводит к ошибке, указывающей, что пользователь не вошел в систему.
Отправка запроса на выход
OpenID Connect end_session_endpoint
позволяет приложению отправлять запрос в платформа удостоверений Майкрософт для завершения сеанса пользователя и очистки файлов cookie, заданных платформа удостоверений Майкрософт. Чтобы полностью подписать пользователя из веб-приложения, приложение должно завершить свой собственный сеанс с пользователем (обычно с помощью очистки кэша маркеров или удаления файлов cookie), а затем перенаправить браузер на:
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/logout?post_logout_redirect_uri=https://localhost/myapp/
Параметр | Тип | Описание |
---|---|---|
tenant |
Обязательно | Значение {tenant} в пути запроса можно использовать для управления тем, кто может войти в приложение. Допустимые значения: common , organizations consumers и идентификаторы клиента. Дополнительные сведения см . в основах протокола. |
post_logout_redirect_uri |
рекомендованный | URL-адрес, к которому должен вернуться пользователь после завершения выхода. Это значение должно соответствовать одному из URI перенаправления, зарегистрированных для приложения. Если он не включен, пользователь отображает универсальное сообщение платформа удостоверений Майкрософт. |