docs: refresh translations, and translate pages in parallel (#3458)
This commit is contained in:
parent
08a3bc8eaf
commit
fd66270926
1 changed files with 4821 additions and 2277 deletions
|
|
@ -1,60 +1,64 @@
|
|||
---
|
||||
translation:
|
||||
sections: [d62c13457fc4a534, 80e73abaca6e0652, d1dc4c54cd00ec9c, 14ad3bc7904036bb, 5225f127bc1b9c77, fe1626fdd5aad1da, 4556cb7ea1a04a31]
|
||||
sections: [d62c13457fc4a534, 80e73abaca6e0652, 128a492d18295f64, 14ad3bc7904036bb, 54a6697833fcc1d9, fe1626fdd5aad1da, 811d083c1da8bcf6]
|
||||
tool: 1
|
||||
---
|
||||
# Авторизація {#authorization}
|
||||
|
||||
Через Streamable HTTP ваш MCP-сервер — це звичайний вебсервіс, і захищати його слід так само, як будь-який інший вебсервіс: bearer-токенами OAuth 2.1.
|
||||
Через Streamable HTTP ваш MCP-сервер — це звичайний вебсервіс, і захищати його треба так само, як будь-який вебсервіс: bearer-токенами OAuth 2.1.
|
||||
|
||||
У термінах OAuth ваш сервер — це **сервер ресурсів** (resource server). Він ніколи нікого не автентифікує й ніколи не видає токенів. Він робить одне: дивиться на заголовок `Authorization` у кожному запиті й вирішує, чи придатний токен у ньому.
|
||||
У термінах OAuth ваш сервер — це **сервер ресурсів**. Він нікого не автентифікує і ніколи не видає токенів. Він робить одне: дивиться на заголовок `Authorization` кожного запиту й вирішує, чи дійсний токен у ньому.
|
||||
|
||||
Ця сторінка — про серверний бік. Клієнт, який знаходить ваш сервер авторизації й отримує токен, описано на сторінці **[Клієнти OAuth](../client/oauth-clients.md)**.
|
||||
Ця сторінка — про серверну частину. Клієнт, який знаходить ваш сервер авторизації й отримує токен, описаний на сторінці **[OAuth-клієнти](../client/oauth-clients.md)**.
|
||||
|
||||
## Три сторони {#the-three-parties}
|
||||
|
||||
* **Сервер авторизації** автентифікує людей і видає токени доступу. Ви його не пишете. Це ваш постачальник ідентичності (Auth0, Keycloak, Entra, ваш власний).
|
||||
* **Сервер авторизації** автентифікує людей і видає токени доступу. Його ви не пишете. Це ваш постачальник ідентичності (Auth0, Keycloak, Entra, власний).
|
||||
* **Сервер ресурсів** — це ваш MCP-сервер. Він перевіряє токен у кожному запиті.
|
||||
* **Клієнт** з'ясовує, якому серверу авторизації ви довіряєте, отримує від нього токен і надсилає його вам як `Authorization: Bearer <token>`.
|
||||
|
||||
Оце й увесь трикутник. Усе на цій сторінці стосується середнього пункту.
|
||||
Оце й увесь трикутник. Усе на цій сторінці — про середній пункт.
|
||||
|
||||
## Верифікатор токенів {#a-token-verifier}
|
||||
|
||||
SDK не має власної думки про те, який вигляд має дійсний токен. Це визначаєте ви, реалізувавши **`TokenVerifier`**:
|
||||
SDK не має власної думки про те, який токен вважати дійсним. Це визначаєте ви, реалізуючи **`TokenVerifier`**:
|
||||
|
||||
```python title="server.py" hl_lines="12-14 19-24"
|
||||
```python title="server.py" hl_lines="14-16 21-27"
|
||||
--8<-- "docs_src/authorization/tutorial001.py"
|
||||
```
|
||||
|
||||
* `TokenVerifier` — це протокол з одним асинхронним методом. `verify_token` отримує сирий токен із заголовка `Authorization` і повертає **`AccessToken`**, якщо він дійсний, або `None`, якщо ні. Більше нічого реалізовувати не треба.
|
||||
* Цей верифікатор шукає токен у таблиці. Справжній перевіряє підпис JWT або звертається до кінцевої точки інтроспекції токенів сервера авторизації. Цей код — ваш; SDK лише викликає його.
|
||||
* `token_verifier=` і `auth=` завжди йдуть разом. Передайте одне без іншого — і `MCPServer(...)` викине `ValueError` ще до того, як обслужить хоч один запит.
|
||||
* `TokenVerifier` — це протокол з одним асинхронним методом. `verify_token` отримує сирий токен із заголовка `Authorization` і повертає **`AccessToken`**, якщо токен дійсний, або `None`, якщо ні. Більше нічого реалізовувати не потрібно.
|
||||
* Цей шукає токен у таблиці; кожен запис фіксує ресурс, для якого токен видано. Справжній перевіряє підпис JWT або викликає кінцеву точку інтроспекції токенів сервера авторизації і повідомляє, для кого видано токен (його `aud`), у `AccessToken.resource`. Цей код — ваш; SDK його лише викликає.
|
||||
* `token_verifier=` і `auth=` завжди йдуть у парі. Передайте одне без іншого — і `MCPServer(...)` викине `ValueError`, ще не обслуживши жодного запиту.
|
||||
|
||||
`AuthSettings` — це публічне обличчя вашого сервера ресурсів:
|
||||
`AuthSettings` — публічне обличчя вашого сервера ресурсів:
|
||||
|
||||
* `issuer_url`: сервер авторизації, що видає ваші токени.
|
||||
* `resource_server_url`: публічний URL цієї MCP-кінцевої точки. Він указує, для *якого* ресурсу призначено токен, і саме тут розміщено документ виявлення.
|
||||
* `resource_server_url`: публічна URL-адреса цієї кінцевої точки MCP. Вона вказує, для *якого* ресурсу призначено токен, і саме за нею лежить документ виявлення.
|
||||
* `required_scopes`: кожен токен мусить містити їх усі.
|
||||
* `validate_token_resource`: відхиляти будь-який токен, чий `AccessToken.resource` не дорівнює `resource_server_url`. Якщо залишити його незаданим, коли `resource_server_url` задано, з'являється попередження (`MCPDeprecationWarning`), а поведінка відповідає `False`; у 3.0 типовим значенням для серверів ресурсів стане `True`.
|
||||
* Увімкніть його, якщо ваш сервер авторизації прив'язує токени до `resource`, який запросив клієнт, — а MCP-клієнти завжди його надсилають. `resource_server_url` має бути точно тією URL-адресою, до якої під'єднуються клієнти.
|
||||
* Залиште вимкненим, якщо ваш сервер авторизації використовує власні ідентифікатори аудиторії (ідентифікатор API в Auth0, ідентифікатор застосунку в Entra), і натомість перевіряйте `aud` у своєму верифікаторі, повертаючи `None` для токена, що не призначений цьому серверу.
|
||||
* Якщо `aud` — список, покладіть у `resource` той елемент, що дорівнює `resource_server_url`.
|
||||
|
||||
!!! tip
|
||||
`examples/servers/simple-auth/` у репозиторії SDK містить `IntrospectionTokenVerifier`, який звертається
|
||||
до кінцевої точки [RFC 7662](https://datatracker.ietf.org/doc/html/rfc7662) справжнього сервера авторизації. Саме таку форму мають більшість продакшн-верифікаторів.
|
||||
У `examples/servers/simple-auth/` у репозиторії SDK є `IntrospectionTokenVerifier`, який викликає
|
||||
кінцеву точку [RFC 7662](https://datatracker.ietf.org/doc/html/rfc7662) справжнього сервера авторизації. Саме таку форму має більшість верифікаторів у реальних розгортаннях.
|
||||
|
||||
## Що з'являється через HTTP {#what-you-get-over-http}
|
||||
## Що ви отримуєте через HTTP {#what-you-get-over-http}
|
||||
|
||||
Авторизація живе в HTTP-заголовках, тож існує лише на HTTP-транспортах. Запустіть сервер на тому, який розгортаєте: `mcp.run(transport="streamable-http")` розміщує його на `http://127.0.0.1:8000/mcp`, а решта — на сторінці **[Запуск сервера](index.md)**. Тепер застосунок має два маршрути:
|
||||
Авторизація живе в HTTP-заголовках, тож існує лише на HTTP-транспортах. Запускайте її на тому, який розгортаєте: `mcp.run(transport="streamable-http")` піднімає сервер на `http://127.0.0.1:8000/mcp`, а решту описано на сторінці **[Запуск сервера](index.md)**. Тепер застосунок має два маршрути:
|
||||
|
||||
```text
|
||||
/mcp
|
||||
/.well-known/oauth-protected-resource/mcp
|
||||
```
|
||||
|
||||
Ви зареєстрували один інструмент. Другий маршрут належить SDK.
|
||||
Ви зареєстрували один інструмент. Другий маршрут — від SDK.
|
||||
|
||||
### Виявлення {#discovery}
|
||||
|
||||
Зробіть `GET` на цей well-known-шлях — і отримаєте **[RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728) Protected Resource Metadata**, побудовані безпосередньо з вашого `AuthSettings`:
|
||||
Зробіть `GET` на цей well-known шлях — і отримаєте **[RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728) Protected Resource Metadata**, побудовані прямо з ваших `AuthSettings`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -65,7 +69,7 @@ SDK не має власної думки про те, який вигляд м
|
|||
}
|
||||
```
|
||||
|
||||
Саме завдяки цьому документу клієнт, який ніколи не чув про ваш сервер, знаходить дорогу: він читає `authorization_servers` і йде туди по токен. Ви не написали з нього жодного рядка.
|
||||
Саме завдяки цьому документу клієнт, який ніколи не чув про ваш сервер, знаходить шлях усередину: він читає `authorization_servers` і йде туди по токен. Ви не написали з нього жодного рядка.
|
||||
|
||||
!!! check
|
||||
Зверніться до `/mcp` без токена (або з таким, для якого ваш верифікатор повернув `None`) — і запит
|
||||
|
|
@ -78,26 +82,26 @@ SDK не має власної думки про те, який вигляд м
|
|||
{"error": "invalid_token", "error_description": "Authentication required"}
|
||||
```
|
||||
|
||||
Нічого не було розібрано, і жоден інструмент не виконався. А вказівник `resource_metadata` у `WWW-Authenticate` —
|
||||
саме те, що робить виявлення автоматичним: 401 -> документ метаданих -> сервер авторизації -> токен -> повторна спроба.
|
||||
Нічого не розібрано, жоден інструмент не виконувався. А вказівник `resource_metadata` у `WWW-Authenticate` —
|
||||
це те, що робить виявлення автоматичним: 401 -> документ метаданих -> сервер авторизації -> токен -> повторна спроба.
|
||||
|
||||
!!! warning
|
||||
Ніщо з цього не захищає `stdio`. Канал не має заголовка `Authorization`, тож `token_verifier` там ніколи
|
||||
не викликається. Межа безпеки `stdio`-сервера — це процес, який його запустив. Те саме
|
||||
стосується `Client(mcp)` у пам'яті, який ви використовуєте в тестах: він під'єднується безпосередньо до об'єкта сервера
|
||||
й оминає HTTP-рівень, разом з авторизацією.
|
||||
Нічого з цього не захищає `stdio`. Канал (pipe) не має заголовка `Authorization`, тож `token_verifier` там ніколи
|
||||
не викликається. Межа безпеки `stdio`-сервера — процес, який його запустив. Те саме
|
||||
стосується `Client(mcp)` у пам'яті, який використовують у тестах: він під'єднується безпосередньо до об'єкта сервера
|
||||
й оминає HTTP-рівень разом з авторизацією.
|
||||
|
||||
## Ідентичність того, хто викликає {#the-callers-identity}
|
||||
|
||||
Усередині будь-якого обробника **`get_access_token()`** — це `AccessToken`, який ваш верифікатор повернув для поточного запиту:
|
||||
|
||||
```python title="server.py" hl_lines="4 32-35"
|
||||
```python title="server.py" hl_lines="4 35-38"
|
||||
--8<-- "docs_src/authorization/tutorial002.py"
|
||||
```
|
||||
|
||||
* Це працює в інструментах, ресурсах і промптах, і нічого нікуди передавати не треба: middleware авторизації зберігає його в контекстній змінній для кожного запиту.
|
||||
* Повертається **той самий об'єкт, який побудував ваш верифікатор**: `client_id`, `scopes`, `subject`, `expires_at` і будь-які додаткові `claims`, які ви додали. Це й є зачіпка для правил на рівні окремих інструментів: прочитайте scopes і відмовте.
|
||||
* Поза автентифікованим HTTP-запитом він повертає `None`. У пам'яті й через `stdio` це завжди `None`.
|
||||
* Це працює в інструментах, ресурсах і промптах, і нічого не треба передавати вручну: middleware авторизації зберігає його в контекстній змінній для кожного запиту.
|
||||
* Повертається **той самий об'єкт, що його побудував ваш верифікатор**: `client_id`, `scopes`, `subject`, `expires_at` і будь-які додаткові `claims`, які ви додали. Це і є зачіпка для правил на рівні окремих інструментів: прочитайте scopes і відмовте.
|
||||
* Поза автентифікованим HTTP-запитом функція повертає `None`. У пам'яті та через `stdio` це завжди `None`.
|
||||
|
||||
Викличте `whoami` з `Authorization: Bearer alice-token` — і модель прочитає:
|
||||
|
||||
|
|
@ -109,22 +113,22 @@ alice (scopes: notes:read)
|
|||
|
||||
SDK дає вам половину сервера ресурсів: перевірити, оголосити, відмовити. Він не дає сторінки входу, екрана згоди чи токена.
|
||||
|
||||
Щоб побачити всі три сторони в русі, запустіть `examples/servers/simple-auth/` з репозиторію SDK (невеликий сервер авторизації та сервер ресурсів, налаштований точно як на цій сторінці), а потім спрямуйте на нього `examples/clients/simple-auth-client/`, щоб пройти повний шлях виявлення й отримання токена.
|
||||
Щоб побачити всі три сторони в русі, запустіть `examples/servers/simple-auth/` з репозиторію SDK (невеликий сервер авторизації та сервер ресурсів, налаштований точно як на цій сторінці), а потім спрямуйте на нього `examples/clients/simple-auth-client/` — і пройдете весь шлях від виявлення до токена.
|
||||
|
||||
!!! info
|
||||
Є другий аргумент конструктора, `auth_server_provider=`, який вбудовує повноцінний сервер
|
||||
авторизації всередину вашого MCP-сервера. Він з'явився ще до розділення AS/RS, навколо якого
|
||||
побудовано специфікацію авторизації MCP. Новим серверам не слід до нього вдаватися.
|
||||
Є ще другий аргумент конструктора, `auth_server_provider=`, який вбудовує повноцінний сервер авторизації
|
||||
всередину вашого MCP-сервера. Він з'явився раніше за розділення AS/RS, навколо якого побудована специфікація
|
||||
авторизації MCP. У нових серверах його використовувати не слід.
|
||||
|
||||
Сервер авторизації також може прийняти підписане твердження корпоративного постачальника ідентичності замість того, щоб користувач проходив екран згоди, і SDK підтримує обидва боки цього обміну. Про цей grant і клієнта, що його пред'являє, — на сторінці **[Твердження ідентичності](../client/identity-assertion.md)**.
|
||||
Сервер авторизації може також прийняти підписане твердження від корпоративного постачальника ідентичності замість того, щоб користувач проклацував екран згоди, і SDK підтримує обидві сторони цього обміну. Цей грант і клієнт, що його пред'являє, описані на сторінці **[Твердження ідентичності](../client/identity-assertion.md)**.
|
||||
|
||||
## Підсумки {#recap}
|
||||
|
||||
* Через Streamable HTTP ваш сервер — це **сервер ресурсів** OAuth 2.1: він перевіряє токени й ніколи їх не видає.
|
||||
* `TokenVerifier` — це вся поверхня інтеграції: один асинхронний метод, на вході токен, на виході `AccessToken | None`.
|
||||
* `token_verifier=` і `auth=AuthSettings(issuer_url=..., resource_server_url=..., required_scopes=[...])` завжди йдуть разом.
|
||||
* Через Streamable HTTP ваш сервер — **сервер ресурсів** OAuth 2.1: він перевіряє токени й ніколи їх не видає.
|
||||
* `TokenVerifier` — уся поверхня інтеграції: один асинхронний метод, токен на вході, `AccessToken | None` на виході.
|
||||
* `token_verifier=` і `auth=AuthSettings(issuer_url=..., resource_server_url=..., required_scopes=[...])` завжди йдуть у парі.
|
||||
* SDK публікує [RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728) Protected Resource Metadata за адресою `/.well-known/oauth-protected-resource/...` і відповідає на неавтентифіковані запити кодом 401, чий заголовок `WWW-Authenticate` вказує на них. Оце й уся історія виявлення.
|
||||
* `get_access_token()` у будь-якому обробнику — це той, хто викликає.
|
||||
* Авторизація — справа HTTP. `stdio` та клієнт у пам'яті ніколи її не бачать.
|
||||
* Авторизація — справа HTTP. `stdio` і тестовий клієнт у пам'яті ніколи її не бачать.
|
||||
|
||||
Клієнтська половина (виявлення вашого сервера авторизації й отримання токена за вас) — на сторінці **[Клієнти OAuth](../client/oauth-clients.md)**. А клієнт, який *стверджує* ідентичність замість того, щоб запитувати її в користувача, — на сторінці **[Твердження ідентичності](../client/identity-assertion.md)**.
|
||||
Клієнтська половина (виявлення сервера авторизації й отримання токена за вас) — на сторінці **[OAuth-клієнти](../client/oauth-clients.md)**. А клієнт, який *стверджує* ідентичність замість того, щоб просити її в користувача, — на сторінці **[Твердження ідентичності](../client/identity-assertion.md)**.
|
||||
|
|
|
|||
Loading…
Reference in a new issue