Программное использование делегированных разрешений в Graph API

Вопрос или проблема

Программное использование делегированных разрешений в Graph API

Согласно документации MS Graphapi, разрешение ChannelMessage.Send доступно только для делегированных прав и недоступно в качестве разрешения приложения.

Поскольку нам нужно использовать делегированные права для отправки сообщения в MS Teams, нам сначала необходимо пройти аутентификацию с пользователем, чтобы использовать GraphAPI для отправки сообщения в канал Teams. Я пытаюсь реализовать это программно, ниже приведён фрагмент кода

from azure.identity import ClientSecretCredential
from msgraph import GraphServiceClient
from msgraph.generated.models.chat_message import ChatMessage
from msgraph.generated.models.item_body import ItemBody


#from azure.identity import DeviceCodeCredential
import os
import asyncio

client_id = os.environ["clientid"]
client_secret = os.environ["clientsecret"]
tenant_id = os.environ["tenenatid"]

credential = ClientSecretCredential(
    tenant_id=tenant_id,
    client_id=client_id,
    client_secret=client_secret,
)
async def send_message():
    scopes = ['https://graph.microsoft.com/.default']
    client = GraphServiceClient(credentials=credential, scopes=scopes)
    print(client)

    request_body = ChatMessage(
        body = ItemBody(
            content = "Hello World",
        ),
    )
    channel_id = os.environ["channel_id"]
    team_id = os.environ["team_id"]
    result =  await client.teams.by_team_id(team_id).channels.by_channel_id(channel_id).messages.post(request_body)
    if result:
        print(result)

if __name__ == "__main__":
    asyncio.run(send_message())

Если я использую ClientSecretCredential для аутентификации, то возникает ошибка

msgraph.generated.models.o_data_errors.o_data_error.ODataError: 
        APIError
        Код: 401
        сообщение: None
        ошибка: MainError(additional_data={}, code="Unauthorized", details=None, inner_error=InnerError(additional_data={}, client_request_id='xxxxxx-412e-4493-xxxx-ccd3667dxxxx', date=DateTime(2024, 9, 20, 10, 58, 16, tzinfo=Timezone('UTC')), odata_type=None, request_id='xxxxxx-da73-4457-xxxx-ee9ea940xxxx'), message="Message POST is allowed in application-only context only for import purposes. Refer to https://docs.microsoft.com/microsoftteams/platform/graph-api/import-messages/import-external-messages-to-teams for more details.", target=None)

Если я использую DeviceCodeCredential для аутентификации, то система просит открыть веб-браузер по адресу https://microsoft.com/devicelogin и ввести код XXXXXX для аутентификации. После аутентификации отправка сообщения в Teams прошла успешно.

Мне нужна ваша помощь, как я могу программно отправить сообщение в канал Teams без входа через браузер

Ответ или решение

Для отправки сообщений в канал Microsoft Teams с использованием Graph API в режиме делегированных разрешений необходимо аутентифицироваться от имени пользователя. Ваш код использует ClientSecretCredential, который предназначен для применения применения разрешений приложения, а не делегированных. По этой причине вы получаете ошибку об отсутствии разрешений.

Чтобы решить вашу задачу без необходимости вручную аутентифицироваться через браузер, вам нужно использовать следующее:

  1. OAuth 2.0 Authorization Code Flow: Это подход, обеспечивающий получение токена доступа для работы от имени пользователя. Обычно этот процесс требует взаимодействия пользователя для предоставления разрешений, но вы можете настроить ваше приложение так, чтобы оно сохраняло токен доступа для последующего использования.

  2. Использование библиотек для работы с миграцией токена: Вы можете хранить полученные токены доступа и обновлять их по мере необходимости, чтобы избежать повторной аутентификации пользователя.

Вот пример подхода с использованием библиотеки msal для Python, которая поможет вам реализовать передачу токена доступа для делегированных разрешений:

import os
import msal
import requests
from msgraph import GraphServiceClient
from msgraph.generated.models.chat_message import ChatMessage
from msgraph.generated.models.item_body import ItemBody

client_id = os.environ["clientid"]
client_secret = os.environ["clientsecret"]
tenant_id = os.environ["tenenatid"]
authority = f'https://login.microsoftonline.com/{tenant_id}'
scope = ['https://graph.microsoft.com/.default']  # для получения разрешений
username = os.environ["username"]  # имя пользователя
password = os.environ["password"]  # пароль

# Создание экземпляра MSAL для получения токена доступа
app = msal.ConfidentialClientApplication(
    client_id,
    authority=authority,
    client_credential=client_secret
)

# Получение токена доступа
result = app.acquire_token_by_username_password(username=username, password=password, scopes=scope)

if "access_token" in result:
    # Создание клиента Graph с полученным токеном доступа
    access_token = result['access_token']
    client = GraphServiceClient(
        credentials=access_token
    )

    # Создание сообщения для отправки
    request_body = ChatMessage(
        body=ItemBody(
            content="Hello World",
        )
    )

    channel_id = os.environ["channel_id"]
    team_id = os.environ["team_id"]

    # Отправка сообщения в канал
    result = client.teams.by_team_id(team_id).channels.by_channel_id(channel_id).messages.post(request_body)

    if result:
        print(result)
else:
    print("Ошибка получения токена:", result.get("error"), result.get("error_description"))

Объяснения кода:

  1. msal.ConfidentialClientApplication: Этот класс используется для получения токенов с использованием учетных данных клиента. Мы используем метод acquire_token_by_username_password для получения токена на основе учетных данных пользователя.

  2. Scopes: Мы указываем, что нам нужны разрешения для Graph API.

  3. Создание GraphServiceClient: Мы создаем экземпляр клиента Graph, передавая токен доступа.

  4. Отправка сообщения: После создания сообщения мы отправляем его в указанный канал Team.

Замечания:

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

Эти шаги помогут вам отправлять сообщения в Teams с использованием разрешений делегирования без необходимости вручную вводить данные в браузере.

Оцените материал
Добавить комментарий

Капча загружается...