Дата публикации
ai_products

Как запустить Claude Desktop в корпорации через Entra ID и Azure API Management без собственного бэкенда

Что нового

Microsoft показала рабочий паттерн, как подключить Claude Desktop к корпоративному деплою Claude на Microsoft Foundry без собственного бэкенда и без раздачи API‑ключей разработчикам.

Ключевые изменения по сравнению с «демо»-сценарием с общим API‑ключом:

  • Вместо общего ключа для всех — вход через Microsoft Entra ID (OIDC + PKCE) прямо из Claude Desktop.
  • В роли шлюза между Claude Desktop и Foundry выступает Azure API Management (APIM):
    • проверяет токен Entra ID по validate-jwt;
    • сам ходит в Foundry с API‑ключом или через Managed Identity;
    • выносит все политики доступа и лимитов в одно место.
  • На ноутбуках разработчиков больше нет секретов:
    • API‑ключ Foundry хранится только в Named value внутри APIM;
    • либо вообще не нужен, если использовать Managed Identity.
  • Claude Desktop 1.5+ работает в режиме Gateway SSO:
    • пользователь логинится в браузере в Entra ID;
    • клиент отправляет в APIM Authorization: Bearer <ID token>;
    • APIM валидирует токен и переаутентифицируется в Foundry.
  • Архитектура полностью завязана на корпоративную идентичность:
    • на каждый запрос есть oid пользователя;
    • можно строить пер‑юзер квоты, отчёты по расходам и дашборды;
    • работают MFA, Conditional Access и Entra ID Protection.

Числа и факты из реализации:

  • API‑версия Foundry для Anthropic‑эндпоинта: 2024-05-01-preview.

  • Формат запроса к Foundry: POST /anthropic/v1/messages?api-version=2024-05-01-preview.

  • Claude Desktop показывает успешное подключение как:

    ✅ Inference — 1-token completion in 1449 ms · via identity provider

  • Для Managed Identity APIM использует ресурс https://cognitiveservices.azure.com.

  • Роль для Foundry при Managed Identity: Foundry User, ID роли 53ca6127-db72-4b80-b1b0-d745d6d5456d (раньше называлась Azure AI User).

  • Для проверки токена Entra ID используется OpenID Discovery: https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration.

Как это работает

Архитектура строится вокруг трёх компонентов Microsoft и одного клиента:

  • Claude Desktop 1.5+ с режимом Gateway SSO.
  • Microsoft Entra ID — источник идентичности и MFA.
  • Azure API Management — шлюз и слой политик.
  • Microsoft Foundry — деплой Claude, к которому идёт трафик.

Поток запросов end‑to‑end

  1. Пользователь в Claude Desktop выбирает корпоративный провайдер и нажимает «Sign in to your organization».

  2. Клиент открывает браузер и делает PKCE‑авторизацию в Entra ID как public client (без client secret) с loopback‑редиректом, например http://127.0.0.1/callback.

  3. Entra ID возвращает ID token Claude Desktop.

  4. Claude Desktop отправляет запрос к шлюзу:

    POST https://<apim-name>.azure-api.net/claude/v1/messages
    Authorization: Bearer <Entra ID ID token>
    anthropic-version: 2023-06-01
    Content-Type: application/json
    
    {
      "model": "<deployment-name>",
      "max_tokens": 64,
      "messages": [{"role": "user", "content": "hi"}]
    }
    
  5. Azure API Management выполняет политику validate-jwt:

    • скачивает OpenID‑метаданные и JWKS по URL вида: https://login.microsoftonline.com/{{entra-tenant-id}}/v2.0/.well-known/openid-configuration;
    • проверяет подпись токена;
    • проверяет aud (должен совпадать с client ID Entra‑приложения Claude Desktop);
    • проверяет iss (issuer должен быть https://login.microsoftonline.com/{{entra-tenant-id}}/v2.0).
  6. После успешной проверки APIM:

    • переназначает backend URL на Foundry: https://<foundry-account>.services.ai.azure.com/anthropic;
    • добавляет api-version=2024-05-01-preview как query‑параметр;
    • выкидывает исходный Authorization из запроса;
    • подставляет либо x-api-key с ключом Foundry, либо заголовок Authorization: Bearer <managed-identity-token>.
  7. Foundry получает уже «чистый» запрос Anthropic‑формата без токена пользователя, выполняет инференс Claude и отвечает APIM.

  8. APIM возвращает ответ в Claude Desktop без каких‑либо секретов или токенов Foundry.

Важный момент: токен пользователя не выходит за пределы APIM. Foundry не знает ничего о токене Entra ID, но в логах APIM остаются все claims, включая oid и email.

Ключевые настройки Entra ID

Для Claude Desktop нужен одиночный tenant, public‑client (PKCE) без client secret и с loopback‑редиректом. Это настраивается как Mobile and desktop applications в Entra ID.

Скрипт PowerShell автоматизирует регистрацию приложения и создаёт Named values в APIM:

# scripts/register-claude-entra-app.ps1
[CmdletBinding()]
param(
  [string] $TenantId       = '<your-tenant-id>',
  [string] $SubscriptionId = '<your-subscription-id>',
  [string] $ResourceGroup  = '<resource-group>',
  [string] $ApimName       = '<apim-name>',
  [string] $AppDisplayName = 'Claude Cowork gateway',
  [string] $RedirectUri    = 'http://127.0.0.1/callback'
)

az account set --subscription $SubscriptionId | Out-Null

# 1. Create (or reuse) the app registration
$appId = az ad app list --display-name $AppDisplayName --query "[0].appId" -o tsv
if (-not $appId) {
  $appId = az ad app create --display-name $AppDisplayName `
            --sign-in-audience AzureADMyOrg --query appId -o tsv
}

# 2. Configure as public PKCE client with the Mobile/Desktop redirect URI
$objectId = az ad app show --id $appId --query id -o tsv
$patch = @{
  publicClient = @{ redirectUris = @($RedirectUri) }
  isFallbackPublicClient = $true
} | ConvertTo-Json -Depth 5 -Compress
az rest --method PATCH `
        --uri "https://graph.microsoft.com/v1.0/applications/$objectId" `
        --headers "Content-Type=application/json" --body $patch | Out-Null

# 3. Ensure a service principal exists
$sp = az ad sp list --filter "appId eq '$appId'" --query "[0].id" -o tsv
if (-not $sp) { az ad sp create --id $appId | Out-Null }

# 4. Push two Named values into APIM for the validate-jwt policy
az apim nv create -g $ResourceGroup --service-name $ApimName `
  --named-value-id entra-tenant-id --display-name entra-tenant-id `
  --value $TenantId --secret false
az apim nv create -g $ResourceGroup --service-name $ApimName `
  --named-value-id entra-client-id --display-name entra-client-id `
  --value $appId --secret false

"Client ID: $appId"

Скрипт делает три вещи:

  • создаёт или переиспользует Entra‑приложение;
  • переводит его в режим public client с loopback‑URI;
  • добавляет в APIM Named values entra-tenant-id и entra-client-id.

Типичная ошибка: если указать redirect URI в разделе Web, Entra ID начнёт требовать client secret. Claude Desktop его не пошлёт, и вы увидите Token exchange failed (HTTP 401).

Политика шлюза в APIM

Основная логика живёт в inbound‑политике API Anthropic в APIM.

<policies>
  <inbound>
    <base />

    <!-- USER → APIM: verify Entra ID token from Claude Desktop -->
    <validate-jwt header-name="Authorization"
                  failed-validation-httpcode="401"
                  failed-validation-error-message="Unauthorized"
                  require-scheme="Bearer">
      <openid-config url="https://login.microsoftonline.com/{{entra-tenant-id}}/v2.0/.well-known/openid-configuration" />
      <audiences>
        <audience>{{entra-client-id}}</audience>
      </audiences>
      <issuers>
        <issuer>https://login.microsoftonline.com/{{entra-tenant-id}}/v2.0</issuer>
      </issuers>
    </validate-jwt>

    <!-- APIM → Foundry -->
    <set-backend-service base-url="https://<foundry-account>.services.ai.azure.com/anthropic" />
    <set-header name="x-api-key" exists-action="override">
      <value>{{foundry-key}}</value>
    </set-header>
    <set-query-parameter name="api-version" exists-action="skip">
      <value>2024-05-01-preview</value>
    </set-query-parameter>
  </inbound>
  <backend><base /></backend>
  <outbound><base /></outbound>
  <on-error><base /></on-error>
</policies>

Пара важных деталей:

  • validate-jwt сам подтягивает JWKS‑ключи, кэширует их и обновляет по мере необходимости.
  • В audiences задаётся ровно один aud — client ID Entra‑приложения Claude Desktop.
  • Исходный Authorization после проверки не пробрасывается дальше.
  • Foundry видит только x-api-key (или Authorization: Bearer <MI-token> при Managed Identity).

Вариант без API‑ключа Foundry (Managed Identity)

Если не хочется хранить ключ Foundry даже в APIM, можно включить системную Managed Identity для APIM и выдать ей роль Foundry User.

  1. Включить System assigned identity: APIM → Identity → System assigned → On.
  2. Назначить этой identity роль Foundry User на аккаунт Foundry (ID роли 53ca6127-db72-4b80-b1b0-d745d6d5456d).
  3. Заменить в политике блок с x-api-key на:
<authentication-managed-identity resource="https://cognitiveservices.azure.com" output-token-variable-name="foundry-token" />
<set-header name="Authorization" exists-action="override">
  <value>@("Bearer " + (string)context.Variables["foundry-token"])</value>
</set-header>

После этого Named value foundry-key не нужен.

Что это значит для вас

Для кого этот паттерн

  • Архитекторы и платформенные команды в корпоративных ИТ, которые внедряют LLM‑клиенты на рабочих станциях и обязаны соблюдать Zero Trust.
  • Разработчики и дата‑саентисты, которым нужно использовать Claude Desktop с внутренним деплоем Claude на Foundry, но которые не хотят поднимать отдельный бэкенд.
  • Безопасность и комплаенс, которым нужны пер‑юзер аудит, MFA и централизованный контроль над доступом к LLM.

Что вы получаете на практике

  1. Нет API‑ключей на ноутбуках:

    • не нужно раздавать ключи Foundry через секрет‑хранилища, MDM и т.п.;
    • нет риска, что ключ уйдёт в GitHub, скриншот или лог.
  2. Пер‑юзер идентичность по умолчанию:

    • каждый запрос к Claude связан с конкретным oid в Entra ID;
    • можно вводить квоты и ограничения на уровне пользователя или группы;
    • легко строить отчёты по расходам и активности.
  3. Единая точка политик и логирования:

    • APIM видит весь трафик к Claude Desktop;
    • можно включить rate limiting, логирование в Application Insights, маршрутизацию по группам;
    • все изменения правил — в одном месте, без переконфигурации клиентов.
  4. Интеграция с корпоративной безопасностью:

    • работают MFA, Conditional Access, Entra ID Protection;
    • при блокировке пользователя в Entra ID он теряет доступ к Claude Desktop автоматически;
    • можно включить Assignment required на Enterprise Application и ограничить доступ только группой.
  5. Упрощённый деплой на рабочие станции:

    • Claude Desktop умеет экспортировать конфиг в .mobileconfig (macOS) и .reg (Windows);
    • эти файлы можно развернуть через Intune, Jamf и другие MDM;
    • пользователю останется только залогиниться в Entra ID.

Где решение помогает

  • Разработка и тестирование: безопасный доступ разработчиков к Claude на Foundry прямо с рабочих машин.
  • Внутренние ассистенты: если вы строите корпоративного помощника на Claude, можно дать сотрудникам прямой доступ через Claude Desktop, сохраняя все политики доступа.
  • Регулируемые отрасли: там, где нельзя раздавать общие ключи и нужен строгий аудит (финансы, госструктуры, медицина).

Где есть ограничения

  • Сценарий требует Azure, Microsoft Foundry и Entra ID. Если инфраструктура в другом облаке, паттерн придётся адаптировать.
  • Потребуется Azure API Management (любой тариф), что добавляет стоимость и ещё один компонент в ландшафте.
  • Foundry Anthropic‑эндпоинт сейчас не реализует GET /v1/models. Для автодискавери моделей в Claude Desktop нужен stub в APIM или ручная настройка.
  • Для России: доступ к Azure, Entra ID и Foundry может требовать VPN и зависит от корпоративной политики и юридических ограничений. Для частных пользователей эта схема, как правило, недоступна.

Место на рынке

Этот паттерн решает конкретную нишу: безопасный доступ к Claude Desktop в корпоративной среде Microsoft без разработки собственного шлюза.

По ключевым параметрам:

  • Безопасность:

    • по уровню контроля идентичности и Zero Trust‑подходу сопоставим с тем, как крупные компании подключают Office 365 и внутренние веб‑приложения к Entra ID;
    • выгодно отличается от классического сценария «клиент + API‑ключ», который до сих пор используют многие клиенты для GPT‑4 и Claude.
  • Инфраструктурные требования:

    • требует Azure API Management и Foundry, в отличие от сценариев, где клиенты бьются напрямую в публичный API Anthropic или OpenAI;
    • зато не нужен собственный бэкенд‑сервис, как в случае кастомных LLM‑шлюзов поверх GPT‑4o или Claude 3.
  • Управляемость:

    • в отличие от самописных прокси на Node.js/Go, политика доступа и логирование здесь живут в APIM и управляются декларативно;
    • добавление новых моделей или ограничений — правка XML‑политики, а не деплой нового сервиса.

Прямых числовых сравнений по скорости или стоимости с другими реализациями шлюзов (например, на базе API Gateway в AWS или Apigee в Google Cloud) здесь нет. Но из потока видно, что накладные расходы — это один дополнительный хоп через APIM и проверка JWT. Для внутренних корпоративных сценариев это обычно приемлемая цена за безопасность и управляемость.

Установка

Ниже — пошаговый план, как повторить схему.

Предварительные требования

  • Аккаунт Azure с:
    • Microsoft Foundry (AI Services) и деплоем Claude (любой вариант Claude, доступный в Foundry);
    • Azure API Management (любой тариф).
  • Права на регистрацию приложений в Entra ID.
  • Claude Desktop версии 1.5.0 или новее.
  • Установленный Azure CLI.

Переменные, которые нужно подставить:

  • <apim-name> — имя сервиса APIM;
  • <resource-group> — ресурсная группа APIM и Foundry;
  • <foundry-account> — имя аккаунта Foundry;
  • <deployment-name> — имя деплоя Claude на Foundry;
  • <tenant-id> и <subscription-id> — из вашего Azure/Entra.

Шаг 1. Регистрация приложения Entra ID для Claude Desktop

  1. Запустите PowerShell‑скрипт register-claude-entra-app.ps1 (см. выше), подставив свои значения tenant, subscription, resource group и APIM.
  2. Скрипт выведет Client ID: <appId> — сохраните его, он нужен в настройках Claude Desktop.
  3. В APIM появятся Named values:
    • entra-tenant-id;
    • entra-client-id.

Если вы случайно создали приложение как Web‑клиент, а не Mobile and desktop, проще удалить его и запустить скрипт ещё раз.

Шаг 2. Создание API в APIM

В Azure Portal:

  1. Перейдите в APIM → APIs → + Add API → HTTP.
  2. Заполните поля:
    • Display name: Anthropic API;
    • Name: anthropicapi;
    • Web service URL: https://<foundry-account>.services.ai.azure.com/anthropic;
    • API URL suffix: claude;
    • Subscription required: Off (подписка не нужна, авторизация идёт по Entra ID).
  3. Добавьте операции:
    • POST /v1/messages — Create message;
    • GET /v1/models — List models (опционально, для stub‑ответа; сам Foundry его не реализует).

Шаг 3. Named value для ключа Foundry (если без Managed Identity)

  1. В APIM откройте Named values → + Add.
  2. Задайте:
    • Name: foundry-key;
    • Type: Secret;
    • Value: API‑ключ из раздела Keys and Endpoint вашего Foundry‑аккаунта.

Этот ключ нигде больше не используется и не уходит на клиент.

Если вы идёте по пути Managed Identity, этот шаг можно пропустить.

Шаг 4. Политика шлюза

  1. В APIM откройте API anthropicapi.
  2. Зайдите в All operations → Inbound processing → </>.
  3. Вставьте политику validate-jwt и проксирование к Foundry (полный XML выше).

Для варианта с Managed Identity замените блок x-api-key на authentication-managed-identity (см. выше).

Шаг 5. Настройка Claude Desktop

В Claude Desktop:

  1. Откройте Configure third-party inference.

  2. Заполните поля:

    • Connection: Gateway.
    • Credential kind: Interactive sign-in.
    • Gateway base URL: https://<apim-name>.azure-api.net/claude.
    • Client ID: <appId> из скрипта.
    • Issuer URL: https://login.microsoftonline.com/<tenant-id>/v2.0.
    • Authorization URL / Token URL: оставить пустыми.
    • Bearer token: ID token (по умолчанию).
    • Scopes: по умолчанию openid profile email offline_access.
    • Redirect port: пусто (эпемерный порт).
    • Model discovery: Off.
  3. В разделе Model list добавьте запись:

    • Model ID: <deployment-name> — имя деплоя Claude на Foundry.
  4. Нажмите Apply Changes, затем Sign in to your organization.

  5. Пройдите авторизацию Entra ID в браузере.

  6. После возврата в приложение Claude Desktop выполнит тест запроса. Успешный запуск выглядит как зелёный баннер:

    ✅ Inference — 1-token completion in 1449 ms · via identity provider

Для массового развёртывания нажмите Export и получите .mobileconfig (macOS) или .reg (Windows) для MDM.

Шаг 6. Проверка цепочки запросов

В APIM:

  1. Откройте APIs → anthropicapi → Test → POST /v1/messages.

  2. Укажите заголовки:

    anthropic-version: 2023-06-01
    
  3. Тело запроса:

    {
      "model": "<deployment-name>",
      "max_tokens": 64,
      "messages": [{"role": "user", "content": "hi"}]
    }
    
  4. Нажмите Send, затем Trace.

Проверьте:

  • Inbound → validate-jwt — статус succeeded, видны claims (oid, email и т.д.).
  • Backend → Request — URL вида: https://<foundry-account>.services.ai.azure.com/anthropic/v1/messages?api-version=2024-05-01-preview; заголовки содержат x-api-key: **** (или Authorization: Bearer **** при Managed Identity), но не содержат исходный Authorization пользователя.
  • Backend → Response — HTTP 200 и JSON‑ответ Claude.

Если вы тестируете из портала без реального токена Entra ID, validate-jwt вернёт 401, а тестовая панель может показать ошибку JavaScript. Временное решение — закомментировать validate-jwt на время теста или использовать curl с настоящим токеном.

Как запустить stub для /v1/models

Если вы хотите оставить Model discovery включённым в Claude Desktop, придётся эмулировать GET /v1/models в APIM.

  1. В API anthropicapi добавьте операцию GET /v1/models.
  2. В её inbound‑политику вставьте:
<policies>
  <inbound>
    <base />
    <return-response>
      <set-status code="200" reason="OK" />
      <set-header name="Content-Type" exists-action="override">
        <value>application/json</value>
      </set-header>
      <set-body>@{
        return new JObject(
          new JProperty("data", new JArray(
            new JObject(
              new JProperty("id", "<deployment-name>"),
              new JProperty("type", "model"),
              new JProperty("display_name", "Claude on Foundry"),
              new JProperty("created_at", "2026-01-01T00:00:00Z")
            )
          )),
          new JProperty("has_more", false),
          new JProperty("first_id", "<deployment-name>"),
          new JProperty("last_id",  "<deployment-name>")
        ).ToString();
      }</set-body>
    </return-response>
  </inbound>
  <backend><base /></backend>
  <outbound><base /></outbound>
  <on-error><base /></on-error>
</policies>

Для нескольких деплоев добавьте несколько объектов в массив data.

Плюс такого подхода — при добавлении нового деплоя Claude достаточно обновить политику APIM, а не пересобирать конфиг Claude Desktop на всех машинах.

Что можно развивать дальше

На базе этой схемы легко нарастить дополнительные механики:

  • Политики llm-token-limit и llm-emit-token-metric в APIM для квот по токенам и мониторинга стоимости.
  • Интеграция с Application Insights и дашборды по oid, группам и приложениям.
  • Включение Assignment required = Yes на Enterprise Application в Entra ID, чтобы только выбранная группа могла логиниться в Claude Desktop.
  • Автоматическое развёртывание .reg / .mobileconfig через Intune, чтобы пользователям не приходилось руками вводить URL шлюза и Client ID.

Главная задача — согласовать между собой Claude Desktop, Entra ID, APIM и Foundry по части того, кто кому доверяет и на каких условиях. В этом паттерне она уже решена, остаётся донастроить политику доступа под ваши процессы.


Читайте также