Платформа удостоверений Майкрософт и поток неявного предоставления разрешения

Платформа удостоверений Майкрософт поддерживает поток неявного предоставления разрешений OAuth 2.0, как описано в спецификации OAuth 2.0. Определяющая характеристика неявного предоставления разрешения заключается в том, что токены (токены идентификаторов или маркеры доступа) возвращаются непосредственно из конечной точки /authorize, а не из конечной точки /token. Это часто используется как часть потока кода авторизации в так называемом "гибридном потоке" — получение токена идентификатора для запроса /authorize вместе с кодом авторизации.

В этой статье описывается, как напрямую запрограммировать протокол в приложении, чтобы запрашивать маркеры из Azure AD. По возможности рекомендуется использовать поддерживаемые библиотеки проверки подлинности Майкрософт (MSAL) вместо получения маркеров и вызова защищенных веб-API. Также ознакомьтесь с примерами приложений, которые используют MSAL.

Совет

Попытайтесь выполнить этот запрос в Postman
Попробуйте выполнить этот запрос и многое другое в Postman — не забудьте заменить токены и идентификаторы!

Преимущества потока кода авторизации

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

Подходящие сценарии для неявного предоставления OAuth2

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

Схема протокола

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

Схема, показывающая неявный поток входа

Отправка запроса на вход

Для первого входа пользователя в приложение можно отправить запрос на авторизацию OpenID Connect и получить id_token с платформы удостоверений Майкрософт.

Важно!

Для успешного запроса токена идентификатора и (или) маркера доступа при регистрации приложения на странице Регистрация приложений на портале Azure должен быть включен соответствующий поток неявного предоставления разрешения. Для этого выберите токены идентификаторов и маркеры доступа в разделе Implicit grant and hybrid flows (Неявное предоставление разрешения и гибридные потоки). Если этого не сделать, будет возвращена следующая ошибка 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=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=id_token
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&scope=openid
&response_mode=fragment
&state=12345
&nonce=678910

Совет

Чтобы проверить вход с помощью неявного потока, щелкните https://login.microsoftonline.com/common/oauth2/v2.0/authorize... После входа в систему браузер должен быть перенаправлен по адресу https://localhost/myapp/, при этом в адресной строке будет id_token.

Параметр Тип Описание
tenant обязательно Значение {tenant} в пути запроса можно использовать для того, чтобы контролировать, кто может входить в приложение. Допустимые значения: common, organizations, consumers, а также идентификаторы клиента. Дополнительные сведения см. в описании основных характеристик протокола. В гостевых сценариях, в которых пользователь из одного клиента выполняет вход в другой, необходимо предоставить идентификатор клиента, чтобы вход выполнялся правильно.
client_id обязательно Идентификатор приложения (клиента), назначенный вашему приложению на странице регистрации приложений на портале Azure.
response_type обязательно Должен включать id_token для входа в OpenID Connect. Этот параметр также может содержать значение token параметра response_type (тип ответа). Использование token здесь позволяет приложению получать токен доступа непосредственно от конечной точки авторизации, при этом отправлять новый запрос на вход в эту конечную точку не требуется. При использовании параметра response_type (тип ответа) token параметр scope должен содержать область, определяющую ресурсы, для которых необходимо выдавать токен (например, user.read в Microsoft Graph). Он также может содержать code вместо token, чтобы предоставить код авторизации для использования в потоке кода авторизации. Этот ответ (id_token + код) иногда называют гибридным потоком.
redirect_uri рекомендуется URI перенаправления приложения, на который можно отправлять ответы проверки подлинности для их получения приложением. Он должен в точности соответствовать одному из URI перенаправления, зарегистрированных на портале, но иметь форму закодированного URL-адреса.
scope обязательно Список областей с разделителями-пробелами. При использовании протокола OpenID Connect (токены id_token) он должен содержать область openid, что преобразуется в разрешение "Вход" в пользовательском интерфейсе предоставления согласия. Если требуется доступ к дополнительным данным пользователя, вы также можете указать области email или profile. Этот запрос может также включать другие области в зависимости от ресурсов, к которым требуется получить доступ, если запрошен маркер доступа.
response_mode необязательно Определяет метод, который следует использовать для отправки созданного маркера запрашивающему приложению. По умолчанию для маркера доступа используется метод query, но если запрос включает токен id_token, значением по умолчанию является fragment.
state рекомендуется Значение, включенное в запрос, которое также возвращается в ответе маркера. Это может быть строка любого контента. Как правило, для предотвращения подделки межсайтовых запросовиспользуется генерируемое случайным образом уникальное значение. Состояние также используется для кодирования сведений о состоянии пользователя в приложении перед выполнением запроса проверки подлинности, например о просматриваемой странице или представлении.
nonce обязательные Значение, включаемое в создаваемый приложением запрос, которое будет использоваться как утверждение в получаемом значении id_token. Приложение может проверять это значение, чтобы устранить атаки с воспроизведением маркеров. Значение обычно представляет собой случайным образом полученную уникальную строку, которую можно использовать для идентификации источника запроса. Требуется только при запросе id_token.
prompt необязательно Указывает требуемый тип взаимодействия с пользователем. На текущий момент единственные допустимые значения — login, none, select_account и consent. При значении prompt=login пользователю придется вводить учетные данные по запросу. Единый вход не сработает. Значение prompt=none является противоположным — оно гарантирует, что интерактивные запросы не будут выводиться ни при каких обстоятельствах. Если запрос не удается выполнить автоматически с помощью единого входа, платформа удостоверений Майкрософт возвращает ошибку. prompt=select_account отправляет пользователя в средство выбора учетных записей, где будут отображаться все учетные записи, запомненные в сеансе. Если установить значение prompt=consent, то после входа пользователь увидит диалоговое окно согласия OAuth с запросом на предоставление разрешений приложению.
login_hint необязательно Этот параметр можно применять для предварительного заполнения полей имени пользователя и электронного адреса на странице входа пользователя (если имя пользователя известно заранее). Этот параметр обычно используется в приложениях при повторной аутентификации после извлечения необязательного утверждения login_hint из предыдущего сеанса входа.
domain_hint необязательно Если указан этот параметр, пропускается процесс обнаружения на основе электронной почты, который нужно проходить на странице входа в приложение. Это несколько упрощает взаимодействие с пользователем. Этот параметр обычно используется для бизнес-приложений, которые работают в одном клиенте, где они будут предоставлять доменное имя в пределах заданного клиента, пересылая пользователя поставщику федерации для этого клиента. Обратите внимание, что это указание не позволяет гостям входить в это приложение и ограничивает использование облачных учетных данных, таких как FIDO.

В этом сценарии пользователю будет предложено ввести учетные данные и выполнить проверку подлинности. Платформа удостоверений Майкрософт также проверяет, согласился ли пользователь предоставить разрешения, указанные в параметре запроса scope. Если пользователь не предоставил какие-либо из этих разрешений, конечная точка запросит их у пользователя. Дополнительные сведения см. в статье Разрешения и предоставление согласия в конечной точке Azure Active Directory версии 2.0.

После того как пользователь пройдет проверку подлинности и предоставит разрешения, платформа удостоверений Майкрософт вернет приложению ответ на указанный 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 будет допустимым. Может не включать все запрошенные области, если они не были применимы к пользователю (только в случае областей Azure AD, которые запрашиваются, когда для входа используется личная учетная запись).
id_token Подписанный JSON Web Token (JWT) Приложение может декодировать сегменты этого токена, чтобы запрашивать сведения о пользователе, выполнившем вход. Эти значения можно кэшировать и (или) отображать в приложении, но их не следует использовать в любых процессах авторизации или обеспечения безопасности. См. дополнительные сведения о маркерах id_token: id_token reference.
Примечание. Предоставляется, только если подан запрос на область openid, а тип response_type содержит id_tokens.
state Если в запрос включен этот параметр состояния, идентичное значение должно содержаться и в ответе на этот запрос. Приложение должно проверить, совпадают ли значения параметра "state" в запросе и ответе.

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

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

Сообщение об ошибке

Сообщения об ошибках также можно отправлять на redirect_uri , чтобы приложение обрабатывало их должным образом:

GET https://localhost/myapp/#
error=access_denied
&error_description=the+user+canceled+the+authentication
Параметр Описание
error Строка кода ошибки, которую можно использовать для классификации типов возникающих ошибок и реагирования на них.
error_description Конкретное сообщение об ошибке, с помощью которого разработчик может определить причину возникновения ошибки проверки подлинности.

Автоматическое получение маркеров доступа в фоновом режиме

Важно!

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

Теперь, когда пользователь вошел в одностраничное приложение, можно автоматически получить маркеры доступа для вызова веб-API, защищенные с помощью платформы удостоверений Майкрософт, например Microsoft Graph. Даже если вы уже получили токен с использованием параметра response_type со значением token, этот метод можно использовать для получения токенов к дополнительным ресурсам. При наличии этих токенов пользователям не нужно повторно выполнять вход.

В обычных потоках OpenID Connect и OAuth токены можно получить, отправив запрос к конечной точке платформы удостоверений Майкрософт/token. Для получения новых токенов для других веб-API можно сделать запрос в скрытом iframe.

// Line breaks for legibility only

https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&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-адресе см. в разделе Отправка запроса на вход.

Совет

Попробуйте скопировать и вставить запрос, показанный ниже, на вкладку браузера. (Не забудьте заменить значения login_hint на правильное значение для вашего пользователя.)

https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=6731de76-14a6-49ae-97bc-6eba6914391e&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={your-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 Позволяет указать одну или несколько областей, для которых access_token будет допустимым. Может не включать все запрошенные области, если они не были применимы к пользователю (только в случае областей Azure AD, которые запрашиваются, когда для входа используется личная учетная запись).
id_token Подписанный JSON Web Token (JWT) Указывается, если параметр response_type содержит значение id_token. Приложение может декодировать сегменты этого токена, чтобы запрашивать сведения о пользователе, выполнившем вход. Эти значения можно кэшировать и (или) отображать в приложении, но их не следует использовать в любых процессах авторизации или обеспечения безопасности. Дополнительные сведения о маркерах id_token см. в статье id_tokenМаркеры идентификаторов.
Примечание. Предоставляется, только если подан запрос на область openid.
state Если в запрос включен этот параметр состояния, идентичное значение должно содержаться и в ответе на этот запрос. Приложение должно проверить, совпадают ли значения параметра "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 пользователю необходимо войти еще раз в интерактивном режиме для получения нового маркера. Этот случай можно обрабатывать любым способом, который лучше всего подходит для вашего приложения.

Обновление маркеров

Неявное предоставление не использует маркеры обновления. Срок действия маркеров id_token и access_token очень короткий, поэтому приложение должно быть готово периодически обновлять их. Чтобы обновить токен любого типа, можно выполнить такой же запрос из скрытого iframe, как показано выше, используя параметр prompt=none для управления поведением платформы удостоверений. Чтобы получить новый id_token, обязательно используйте id_token в response_type и scope=openid, а также параметр nonce.

В браузерах, которые не поддерживают сторонние файлы cookie, это приведет к ошибке, указывающей, что пользователь не вошел в приложение.

Отправка запроса на выход

Конечная точка end_session_endpoint OpenID Connect позволяет приложению отправить запрос на платформу удостоверений Майкрософт, чтобы завершить сеанс пользователя и очистить файлы 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) перенаправления, зарегистрированных для приложения. Если оно не указано, то пользователю будет показано универсальное сообщение платформы удостоверений Майкрософт.

Дальнейшие действия

  • Перейдите на страницу примеров MSAL JS, чтобы приступить к созданию кода.
  • Рассмотрите поток кода авторизации как более новую, лучшую альтернативу неявному предоставлению разрешения.