Я запрашиваю следующие области (с кодировкой URL):
offline_access user.read https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send
Процесс авторизации с OAuth 2.0 с использованием нового API Microsoft Graph работает нормально, но при использовании токена доступа для подключения к IMAP через XOAuth2 я получаю NO AUTHENTICATE
, что указывает на то, что токен недействителен.
Оказывается, проблема не в пользователе, а в Microsoft Graph API. Несмотря на то, что это не задокументировано, в настоящее время вам не разрешено запрашивать токен с областью действия, подпадающей под действие двух арендаторов, или он выберет один и завершится ошибкой.
В этом случае User.Read
подпадает под аренду Microsoft Graph. С технической точки зрения, если ваш пользователь является корпоративным пользователем Outlook/Office365, у него, скорее всего, не установлен Microsoft Graph, и правильная область действия будет https://outlook.office.com/User.Read
. Однако конечная точка профиля Outlook устарела, и ее использование нецелесообразно (у вас также нет возможности узнать, есть ли у вашего пользователя арендатор MS Graph). Кажется, чтобы решить эту проблему, разрешение user.read
можно запросить без указания URL-адреса Microsoft Graph.
По сути, это то, что вы делаете выше, но это может ввести в заблуждение, поскольку вы на самом деле не запрашиваете общее разрешение User.Read, которое затем может быть разрешено клиенту Outlook. На самом деле происходит то, что разрешение User.Read сопоставляется с некоторым арендатором по умолчанию, поэтому ваши области фактически содержат несколько арендаторов (как арендатор по умолчанию, так и Outlook).
Поскольку это не разрешено, он автоматически завершается сбоем и по умолчанию используется арендатор по умолчанию. С большинством их API это все еще работает, но, в частности, с IMAP/SMTP вы не можете запросить большую область действия/мультитенантный ключ, иначе он не будет проверяться через XOAuth2. Вы заметите, что токены доступа, возвращаемые только для IMAP/SMTP, всегда намного меньше, чем токены доступа для других областей.
Чтобы исправить это, вам нужно будет запросить два токена доступа. Во-первых, вы должны использовать свой код авторизации для запроса ключа в следующих пределах:
offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send
После этого вам необходимо запросить токен доступа к профилю. Однако с октября 2020 г. вам больше не разрешено использовать один код авторизации для предоставления нескольких токенов доступа. Поэтому вам нужно будет снова войти в систему пользователя — канонический способ сделать это — просто вернуться к URL-адресу авторизации, оставив поле login_hint
пустым. Это будет зависеть от того, как вы создаете свой URL-адрес, но вот пример в JS:
url = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize?'
url += `client_id=${clientId}`
url += '&response_type=code'
url += '&redirect_uri=${redirectURI}'
url += '&response_mode=query'
url += '&login_hint='
url += '&scope=offline_access%20User.Read%20https%3A%2F%2Foutlook.office.com%2FIMAP.AccessAsUser.All%20https%3A%2F%2Foutlook.office.com%2FSMTP.Send'
url += '&state=12345
Обратите внимание, что ваш код авторизации должен запрашивать полную область действия (включая области User.Read
и области IMAP, такие как IMAP.AccessAsUser.All
, для обоих запросов токена доступа. Указание меньшей области действия не гарантирует, что читаемый вами профиль обязательно будет соответствовать учетной записи Outlook.
После получения этого второго кода авторизации (он не будет просить пользователя снова войти в систему вручную, просто немного загрузит и автоматически разрешит второй код) вы можете запросить новый токен доступа со следующей областью действия:
user.read
Вы можете включить любые другие области API Graph выше, но указание чего-либо в Outlook и особенно в IMAP приведет к смешению ваших областей. Область ответа по-прежнему будет содержать доступ к EAS и области Outlook, но с добавлением разрешения user.read
.
Вы должны использовать этот второй токен для доступа к профилю и обновлять его отдельно от первого токена (который следует использовать только для IMAP/SMTP).