> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-fix-nav-issues.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Руководство по аутентификации на основе JWT и эфемерным пользователям в ClickHouse Cloud

# Аутентификация JWT

export const CloudOnlyBadge = () => {
  return <div className="cloudBadge">
            <div className="cloudIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path fillRule="evenodd" clipRule="evenodd" d="M5.33395 12.6667H12.3739C13.6593 12.6667 14.7073 11.6187 14.7073 10.3334C14.7073 9.04804 13.6593 8.00004 12.3739 8.00004H12.0839V7.33337C12.0839 5.12671 10.2906 3.33337 8.08395 3.33337C6.09928 3.33337 4.45395 4.78537 4.14195 6.68204C2.55728 6.76271 1.29395 8.06204 1.29395 9.66671C1.29395 11.3234 2.63728 12.6667 4.29395 12.6667H5.33395Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
        </div>
            {'ClickHouse Cloud only'}
        </div>;
};

ClickHouse может аутентифицировать пользователей с помощью JSON Web Tokens (JWT). В отличие от других внешних аутентификаторов, таких как [LDAP](/ru/concepts/features/security/external-authenticators/ldap) или [Kerberos](/ru/concepts/features/security/external-authenticators/kerberos), JWT-аутентификация не проверяет подлинность уже существующих пользователей. Вместо этого она динамически создаёт **эфемерных пользователей** на основе утверждений, встроенных в каждый токен. Эти пользователи существуют только в памяти, получают права доступа, определяемые утверждениями токена, и автоматически удаляются после истечения срока действия токена.

Это принципиально отличает JWT-аутентификацию от методов на основе паролей или сертификатов: оператора `CREATE USER ... IDENTIFIED WITH jwt` не существует, и попытка выполнить его вызывает исключение. JWT-пользователи полностью управляются жизненным циклом токена.

<div id="overview">
  ## Обзор
</div>

Процесс аутентификации выглядит следующим образом:

1. Клиент передаёт подписанный JWT одним из поддерживаемых способов (через HTTP-заголовок `Authorization: Bearer`, TCP собственный протокол или поле gRPC `jwt`).
2. ClickHouse проверяет подпись токена.
3. Проверяются обязательные утверждения (`exp`, `iat`, `iss`, `sub`, `aud`).
4. В памяти создаётся эфемерный пользователь с правами доступа, сформированными на основе утверждений токена `clickhouse:grants` и `clickhouse:roles` и ограниченными верхней границей разрешений.
5. Когда срок действия токена истекает, пользователя удаляет фоновая задача сборки мусора.

<div id="token-claims">
  ## Утверждения в токене
</div>

<div id="required-claims">
  ### Обязательные утверждения
</div>

Каждый JWT, передаваемый в ClickHouse, должен содержать следующие утверждения:

| Утверждение | Описание                                                                                                                    |
| ----------- | --------------------------------------------------------------------------------------------------------------------------- |
| `alg`       | Алгоритм подписи (утверждение в заголовке). Поддерживаемые значения: `HS256`, `RS256`, `ES256`.                             |
| `exp`       | Время истечения срока действия. Задаёт `valid_until` эфемерного пользователя.                                               |
| `iat`       | Время выпуска. Используется для предотвращения повторного использования более старых токенов для одного и того же identity. |
| `iss`       | Издатель. Сопоставляется с ожидаемым издателем провайдера.                                                                  |
| `sub`       | Subject. Становится частью сгенерированного имени пользователя.                                                             |
| `aud`       | Аудитория. Сопоставляется с ожидаемой аудиторией провайдера.                                                                |

Утверждение `kid` (идентификатор ключа) в заголовке также обязательно при использовании разрешения ключей на основе JWKS.

<Info>
  **Режим JWKS поддерживает только ключи RSA**

  Хотя провайдеры со статическими ключами принимают любой из алгоритмов `HS256`, `RS256` или `ES256`, провайдеры на основе JWKS принимают только JWK, у которых `kty` равно `RSA` (то есть токены, подписанные с помощью `RS256`). Токены, подписанные ключами HMAC (`HS256`) или EC (`ES256`), не могут быть проверены через конечную точку JWKS и будут отклонены.
</Info>

<div id="other-recognized-claims">
  ### Другие распознаваемые утверждения
</div>

| Утверждение | Описание                                                                                                                                                        |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `nbf`       | Время, раньше которого токен не действует. Это утверждение не является обязательным, но если оно присутствует, токены отклоняются до наступления этого времени. |
| `jti`       | Зарезервировано. Принимается в токенах, но в настоящее время не проверяется и не используется.                                                                  |

<div id="optional-claims">
  ### Необязательные утверждения
</div>

| Утверждение                                                                                                                                                      | Имя по умолчанию    | Описание                                                                                                                                               |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Привилегии                                                                                                                                                       | `clickhouse:grants` | JSON-массив фрагментов SQL `GRANT`, например `["SELECT ON db.*", "INSERT ON db.table1"]`. Каждый элемент разбирается как содержимое оператора `GRANT`. |
| Роли                                                                                                                                                             | `clickhouse:roles`  | JSON-массив имён ролей для назначения, например `["analyst", "reader"]`.                                                                               |
| Имена утверждений по умолчанию можно переопределить, указав пользовательские имена, если ваш провайдер идентификации использует другие соглашения об именовании. |                     |                                                                                                                                                        |

<div id="example-token-header-and-payload">
  ### Пример токена, заголовка и полезной нагрузки
</div>

```json theme={null}
{
  "alg": "RS256",
  "kid": "my-key-id"
}
```

```json theme={null}
{
  "iss": "https://idp.example.com",
  "sub": "jane.doe",
  "aud": "my-clickhouse-cluster",
  "exp": 1719504000,
  "iat": 1719500400,
  "clickhouse:grants": ["SELECT ON analytics.*", "INSERT ON analytics.events"],
  "clickhouse:roles": ["analyst"]
}
```

<div id="ephemeral-user-behavior">
  ## Поведение эфемерного пользователя
</div>

Пользователи JWT отличаются от обычных пользователей ClickHouse по нескольким важным аспектам.

<div id="identity-and-naming">
  ### Идентификация и именование
</div>

Каждый пользователь JWT получает детерминированный UUID, вычисляемый на основе утверждений `iss`, `sub` и `aud`. Этот UUID остается **стабильным** при разных входах в систему. Пользователь, который входит в систему несколько раз с разными токенами (но с тем же издателем, субъектом и аудиторией), всегда получает один и тот же UUID.

Однако имя пользователя **непостоянно**. Оно формируется следующим образом:

```text theme={null}
JWT::<issuer>::<audience>::<subject>::<claims_hash>
```

Часть `<claims_hash>` изменяется всякий раз, когда изменяются утверждения `clickhouse:roles` или `clickhouse:grants`. Это означает, что токены с разными наборами ролей или привилегий будут давать разные имена пользователей даже для одной и той же учетной записи.

<div id="access-rights">
  ### Права доступа
</div>

Эффективные права доступа определяются следующим образом:

```text theme={null}
effective_rights = permission_limit ∩ (token_grants ∪ token_roles)
```

Где `permission_limit` — это набор прав доступа у эталонной роли или пользователя, заданных в качестве верхней границы. Права, запрашиваемые токеном сверх этого предела, отбрасываются без уведомления.

<div id="token-freshness">
  ### Актуальность токена
</div>

ClickHouse отслеживает утверждение `iat` (время выдачи) у последнего аутентифицированного токена для каждой стабильной идентичности. Если предъявляется токен, у которого `iat` совпадает с сохранённым значением или меньше него, server повторно использует существующего эфемерного пользователя без повторной проверки утверждений. Это не позволяет более старым токенам снижать разрешения пользователя.

<div id="lifetime-and-garbage-collection">
  ### Срок жизни и сборка мусора
</div>

Эфемерные пользователи создаются при первой успешной аутентификации токена и удаляются фоновой задачей сборки мусора после истечения `valid_until` (который вычисляется из `exp`). Интервал запуска GC задаётся параметром `gc_interval` (по умолчанию — 5 минут).

Между запусками GC пользователи с истёкшим сроком действия могут по-прежнему отображаться в `system.users`, но аутентифицироваться уже не смогут.

<div id="persistent-access-assignments">
  ### Постоянные назначения прав доступа
</div>

Поскольку UUID стабилен, вы можете назначать JWT-пользователю профили настроек, квоты, политики доступа к строкам и политики маскирования столбцов с помощью SQL-команд. Эти назначения сохраняются в хранилище управления доступом (на диске или в ZooKeeper) и остаются в силе после истечения срока действия токена и повторной аутентификации.

Указывайте пользователя по его текущему имени:

```sql theme={null}
ALTER SETTINGS PROFILE my_profile ADD TO 'JWT::ClickHouse::my-service-id::jane.doe::<claims-hash>';
```

<Note>
  Имя пользователя и UUID для заданной идентификационной сущности можно найти в столбцах `name` и `id` таблицы `system.users`, пока пользователь активен.
</Note>

Обратите внимание, что `ALTER USER` не работает напрямую с пользователями JWT, так как они доступны только в режиме только для чтения. Чтобы назначить профили настроек, квоты или политики, используйте команды `ALTER SETTINGS PROFILE`, `ALTER QUOTA` или `ALTER ROW POLICY`, как показано выше.

<div id="differences-from-regular-users">
  ## Отличия от обычных пользователей
</div>

| Характеристика                         | JWT-пользователи                                                               | Обычные пользователи                               |
| -------------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------- |
| Создание                               | Автоматически на основе утверждений токена                                     | Оператор `CREATE USER`                             |
| Хранение                               | Только в памяти (эфемерно)                                                     | На диске, в ZooKeeper или в конфигурационном файле |
| `CREATE USER ... IDENTIFIED WITH jwt`  | Не поддерживается (вызывает исключение)                                        | Поддерживаются все остальные типы аутентификации   |
| `ALTER USER` / `DROP USER`             | Не поддерживается                                                              | Поддерживаются                                     |
| Резервное копирование и восстановление | Не включается                                                                  | Включается                                         |
| Имя пользователя                       | Генерируется автоматически, может меняться                                     | Выбирается администратором, фиксированное          |
| UUID                                   | Детерминированно выводится из `iss`+`sub`+`aud`                                | Случайный при создании                             |
| Срок жизни                             | Ограничен значением `exp` токена                                               | До явного удаления                                 |
| Права доступа                          | Определяются утверждениями токена и ограничиваются верхней границей разрешений | Явно выдаются через `GRANT`                        |
| Ограничения по хостам                  | Сетевая конфигурация на уровне провайдера                                      | Предложение `HOST` для пользователя                |
| Профили настроек                       | Можно назначать по UUID (постоянно)                                            | Настраиваются напрямую                             |
| Квоты и политики строк                 | Можно назначать по UUID (постоянно)                                            | Настраиваются напрямую                             |
| Роли по умолчанию                      | Не настраиваются                                                               | Настраиваются                                      |

<div id="sql-security-definer-views">
  ## Представления с SQL SECURITY DEFINER
</div>

Когда эфемерный JWT-пользователь создаёт представление с `SQL SECURITY DEFINER`, сервер автоматически создаёт постоянную теневую копию пользователя, которая выступает в качестве определителя представления. Этот теневой пользователь:

* Имеет имя `<original_jwt_username>:definer`
* Имеет `NO_AUTHENTICATION` (не может использоваться для входа)
* Сохраняет те же права доступа, что и исходный JWT-пользователь на момент создания представления

Это гарантирует, что представление продолжит работать после истечения срока действия токена эфемерного пользователя и удаления исходного пользователя в ходе сборки мусора.

<div id="client-usage">
  ## Использование клиента
</div>

<div id="passing-token-directly">
  ### Передача токена напрямую
</div>

Используйте флаг `--jwt` с `clickhouse-client` для аутентификации с помощью заранее полученного токена:

```bash theme={null}
clickhouse-client --host your-instance.clickhouse.cloud --secure --jwt '<your_jwt_token>'
```

<Note>
  Флаг `--jwt` нельзя использовать вместе с `--user`. Если указан `--jwt`, имя пользователя берётся из токена.
</Note>

<div id="http-interface">
  ### HTTP-интерфейс
</div>

Передайте токен в заголовке `Authorization` как Bearer-токен:

```bash theme={null}
curl -H 'Authorization: Bearer <your_jwt_token>' \
    'https://your-instance.clickhouse.cloud:8443/?query=SELECT+currentUser()'
```

<Warning>
  Всегда передавайте JWT только по HTTPS. Bearer-токен, отправленный по обычному HTTP, может быть перехвачен любым узлом на сетевом пути, что равносильно утечке учетных данных.
</Warning>

<div id="oauth2-device-code-login">
  ### Вход по коду устройства OAuth2
</div>

`clickhouse-client` поддерживает интерактивный OAuth2-поток Device Code через флаг `--login`. Для конечных точек ClickHouse Cloud клиент автоматически выполняет обмен токенов, чтобы получить JWT для ClickHouse. Токены прозрачно обновляются в течение сеанса. При получении нового токена клиент автоматически переподключается.

```bash theme={null}
clickhouse-client --host your-instance.clickhouse.cloud --login
```

<div id="clickhouse-cloud-built-in">
  ## Встроенный JWT-аутентификатор ClickHouse Cloud
</div>

У каждого сервиса ClickHouse Cloud есть предопределённый JWT-аутентификатор, который используется в SQL Console и в процессе входа `clickhouse-client` с параметром `--login`. Этот аутентификатор настроен следующим образом:

| Параметр         | Значение                                                      |
| ---------------- | ------------------------------------------------------------- |
| `iss` (issuer)   | `ClickHouse`                                                  |
| `aud` (audience) | UUID сервиса (виден в URL консоли Cloud)                      |
| `sub` (subject)  | Адрес электронной почты вашей учётной записи ClickHouse Cloud |

Для встроенного аутентификатора верхняя граница разрешений установлена на роль `default_role` и пользователя `default`. Это означает, что итоговые права любого JWT-пользователя ограничиваются пересечением с привилегиями этих двух сущностей, поэтому токен никогда не сможет повысить привилегии сверх того, что разрешено `default_role` и `default`.

Чтобы использовать этот аутентификатор, ничего настраивать не нужно. Он создаётся автоматически при создании сервиса.

<div id="interserver-communication">
  ## Межсерверное взаимодействие
</div>

Когда запрос перенаправляется на другой сегмент или реплику, JWT-токен передаётся в межсерверном протоколе. Удалённый узел повторно аутентифицирует токен независимо, создавая собственного эфемерного пользователя.

<div id="troubleshooting">
  ## Устранение неполадок
</div>

* **Права доступа не предоставлены:** У указанной роли или пользователя может не быть необходимых привилегий. Убедитесь, что роли, указанные в `clickhouse:roles`, существуют и включают соответствующие привилегии.
* **Токен отклонён:** Убедитесь, что `iss`, `aud` и алгоритм подписи в вашем токене соответствуют ожидаемым провайдером JWT. Если используется JWKS, убедитесь, что `kid` токена соответствует ключу в наборе ключей провайдера.
* **Пользователь исчезает между запросами:** Эфемерные пользователи удаляются после истечения срока действия токена. Для длительных сеансов используйте клиент, поддерживающий обновление токена (например, режим `--login`).
* **`CREATE USER ... IDENTIFIED WITH jwt` завершается с ошибкой:** Это ожидаемое поведение. Пользователей JWT нельзя создавать через DDL. Ими полностью управляет жизненный цикл токена.
