Я пытаюсь перейти от использования API Graph от выполнения HTTP-запросов через requests к использованию Python SDK. Я использовал метод acquire_token_by_username_password, и запросы обрабатывались правильно. При переходе на использование Python SDK я создаю свой клиент следующим образом:
credential = UsernamePasswordCredential(
client_id=self._client_id,
username=username,
password=password,
)
return GraphServiceClient(credential, self._scopes)
а затем пытаюсь выполнить запрос типа:await client.users.get(request_configuration=request_configuration)
Однако с теми же учетными данными, которые я использовал в методе HTTP, я получаю:
APIError
Code: 403
message: None
error: MainError(additional_data = {}, code='Authorization_RequestDenied', details=None, inner_error=InnerError(additional_data = {}, client_request_id='53e56211-cd3d-47d5-b3fb-b6dacd6088a8', date=DateTime(2024, 2, 25, 11, 10, 15, tzinfo=Timezone('UTC')), odata_type=None, request_id='4b92be4e-d60a-4040-bcb4-e8d11a636879'), message='Insufficient privileges to complete the operation.', target=None)
Я попытался повторно дать согласие на (делегированные) разрешения в Azure; не уверен, что еще я могу сделать.






Ошибка обычно возникает, если у пользователя или субъекта-службы нет необходимых разрешений или ролей для выполнения операции.
Первоначально я тоже получил ту же ошибку, когда передал User.Read в области, которых недостаточно для перечисления пользователей:

Чтобы устранить ошибку, вам необходимо добавить как минимум User.Read.All Делегированное разрешение при регистрации приложения, предоставив на это согласие администратора:

Когда я запустил приведенный ниже модифицированный код, изменив значение области видимости на User.Read.All, я успешно получил ответ от пользователей следующим образом:
import asyncio
from msgraph import GraphServiceClient
from azure.identity import UsernamePasswordCredential
credential = UsernamePasswordCredential(
client_id = "appId",
username = "[email protected]",
password = "xxxxxxxxxx",
)
scopes=['User.Read.All']
client = GraphServiceClient(credential, scopes=scopes)
async def get_users():
try:
users = await client.users.get()
for user in users.value:
print(user.display_name)
except Exception as e:
print(e)
asyncio.run(get_users())
Ответ:

Ссылка: Список пользователей — Microsoft Graph
Сработало ли это, когда вы изменили область действия на User.Read.All?
Когда вы используете /.default в качестве области действия с потоком паролей имени пользователя, токен будет создан со всеми делегированными разрешениями, предоставленными в приложении. Но в редких случаях, когда это не работает, лучше попробовать использовать области, специфичные для вызовов API.
Это сработало, когда я изменил его на User.Read.All, я не менял его в других потоках и оставил /.default, и это сработало. Думаю, это один из тех редких случаев!
Интересный. Означает ли это, что мне нужно изменить области для каждого запроса конечной точки API Graph? У меня сложилось впечатление (возможно, ошибочное), что я могу использовать области по умолчанию, если приложение, зарегистрированное в Azure, имеет правильные делегированные разрешения.