Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s
190 lines
9.9 KiB
Plaintext
190 lines
9.9 KiB
Plaintext
---
|
||
title: OAuth
|
||
icon: key
|
||
description: Поток авторизационного кода с PKCE и учётными данными клиента для доступа между серверами.
|
||
---
|
||
|
||
Twenty реализует OAuth 2.0 с потоком авторизационного кода + PKCE для пользовательских приложений и с учётными данными клиента для доступа между серверами. Клиенты регистрируются динамически по [RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591) — никакой ручной настройки в панели управления.
|
||
|
||
## Когда использовать OAuth
|
||
|
||
| Сценарий | Метод аутентификации |
|
||
| ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------ |
|
||
| Внутренние скрипты, автоматизация | [Ключ API](/l/ru/developers/extend/api#authentication) |
|
||
| Внешнее приложение, действующее от имени пользователя | **OAuth — авторизационный код** |
|
||
| Между серверами, без контекста пользователя | **OAuth — клиентские учётные данные** |
|
||
| Приложение Twenty с расширениями пользовательского интерфейса (UI) | [Приложения](/l/ru/developers/extend/apps/getting-started/quick-start) (OAuth обрабатывается автоматически) |
|
||
|
||
## Зарегистрировать клиента
|
||
|
||
Twenty поддерживает **динамическую регистрацию клиентов** по [RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591). Ручная настройка не требуется — регистрируйте программно:
|
||
|
||
```bash
|
||
POST /oauth/register
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"client_name": "My Integration",
|
||
"redirect_uris": ["https://myapp.com/callback"],
|
||
"grant_types": ["authorization_code"],
|
||
"token_endpoint_auth_method": "client_secret_post"
|
||
}
|
||
```
|
||
|
||
**Ответ:**
|
||
|
||
```json
|
||
{
|
||
"client_id": "abc123",
|
||
"client_secret": "secret456",
|
||
"client_name": "My Integration",
|
||
"redirect_uris": ["https://myapp.com/callback"]
|
||
}
|
||
```
|
||
|
||
<Warning>
|
||
Храните `client_secret` в надёжном месте — позже его нельзя будет получить.
|
||
</Warning>
|
||
|
||
## Области действия
|
||
|
||
| Область действия | Доступ |
|
||
| ---------------- | ----------------------------------------------------------- |
|
||
| `api` | Полный доступ на чтение/запись к Core и Metadata API |
|
||
| `profile` | Чтение информации профиля аутентифицированного пользователя |
|
||
|
||
Запрашивайте области действия как строку, разделённую пробелами: `scope=api profile`
|
||
|
||
## Поток авторизационного кода
|
||
|
||
Используйте этот поток, когда ваше приложение действует от имени пользователя Twenty.
|
||
|
||
### 1. Перенаправьте пользователя для авторизации
|
||
|
||
```
|
||
GET /oauth/authorize?
|
||
client_id=YOUR_CLIENT_ID&
|
||
response_type=code&
|
||
redirect_uri=https://myapp.com/callback&
|
||
scope=api&
|
||
state=random_state_value&
|
||
code_challenge=CHALLENGE&
|
||
code_challenge_method=S256
|
||
```
|
||
|
||
| Параметр | Обязательно | Описание |
|
||
| ----------------------- | ------------- | --------------------------------------------------------------- |
|
||
| `client_id` | Да | Идентификатор вашего зарегистрированного клиента |
|
||
| `response_type` | Да | Должно быть `code` |
|
||
| `redirect_uri` | Да | Должен совпадать с зарегистрированным redirect URI |
|
||
| `scope` | Нет | Области действия, разделённые пробелами (по умолчанию `api`) |
|
||
| `state` | Рекомендуется | Случайная строка для предотвращения CSRF-атак |
|
||
| `code_challenge` | Рекомендуется | Вызов PKCE (хэш SHA-256 от верификатора, в кодировке base64url) |
|
||
| `code_challenge_method` | Рекомендуется | Должно быть `S256` при использовании PKCE |
|
||
|
||
Пользователь видит экран согласия и подтверждает или отклоняет доступ.
|
||
|
||
### 2. Обработайте обратный вызов
|
||
|
||
После авторизации Twenty перенаправляет обратно на ваш `redirect_uri`:
|
||
|
||
```
|
||
https://myapp.com/callback?code=AUTH_CODE&state=random_state_value
|
||
```
|
||
|
||
Проверьте, что `state` совпадает с отправленным значением.
|
||
|
||
### 3. Обменяйте код на токены
|
||
|
||
```bash
|
||
POST /oauth/token
|
||
Content-Type: application/x-www-form-urlencoded
|
||
|
||
grant_type=authorization_code&
|
||
code=AUTH_CODE&
|
||
redirect_uri=https://myapp.com/callback&
|
||
client_id=YOUR_CLIENT_ID&
|
||
client_secret=YOUR_CLIENT_SECRET&
|
||
code_verifier=YOUR_PKCE_VERIFIER
|
||
```
|
||
|
||
**Ответ:**
|
||
|
||
```json
|
||
{
|
||
"access_token": "eyJhbG...",
|
||
"token_type": "Bearer",
|
||
"expires_in": 3600,
|
||
"refresh_token": "dGhpcyBpcyBh..."
|
||
}
|
||
```
|
||
|
||
### 4. Используйте токен доступа
|
||
|
||
```bash
|
||
GET /rest/companies
|
||
Authorization: Bearer ACCESS_TOKEN
|
||
```
|
||
|
||
### 5. Обновляйте при истечении срока действия
|
||
|
||
```bash
|
||
POST /oauth/token
|
||
Content-Type: application/x-www-form-urlencoded
|
||
|
||
grant_type=refresh_token&
|
||
refresh_token=YOUR_REFRESH_TOKEN&
|
||
client_id=YOUR_CLIENT_ID&
|
||
client_secret=YOUR_CLIENT_SECRET
|
||
```
|
||
|
||
## Поток клиентских учётных данных
|
||
|
||
Для интеграций между серверами без участия пользователя:
|
||
|
||
```bash
|
||
POST /oauth/token
|
||
Content-Type: application/x-www-form-urlencoded
|
||
|
||
grant_type=client_credentials&
|
||
client_id=YOUR_CLIENT_ID&
|
||
client_secret=YOUR_CLIENT_SECRET&
|
||
scope=api
|
||
```
|
||
|
||
Возвращаемый токен имеет доступ на уровне рабочей области и не привязан к конкретному пользователю.
|
||
|
||
## Обнаружение сервера
|
||
|
||
Twenty публикует свою конфигурацию OAuth на стандартной конечной точке обнаружения:
|
||
|
||
```
|
||
GET /.well-known/oauth-authorization-server
|
||
```
|
||
|
||
Это возвращает все конечные точки, поддерживаемые типы грантов, области действия и возможности — полезно для создания универсальных OAuth-клиентов.
|
||
|
||
## Сводка конечных точек API
|
||
|
||
| Конечная точка | Назначение |
|
||
| ----------------------------------------- | --------------------------------- |
|
||
| `/.well-known/oauth-authorization-server` | Обнаружение метаданных сервера |
|
||
| `/oauth/register` | Динамическая регистрация клиентов |
|
||
| `/oauth/authorize` | Авторизация пользователя |
|
||
| `/oauth/token` | Обмен и обновление токена |
|
||
|
||
| Среда | Базовый URL |
|
||
| --------------------------- | ------------------------ |
|
||
| **Облако** | `https://api.twenty.com` |
|
||
| **Самостоятельный хостинг** | `https://{your-domain}` |
|
||
|
||
## OAuth против ключей API
|
||
|
||
| | API ключи | OAuth |
|
||
| ------------------------------- | ------------------------------------- | ----------------------------------------------------- |
|
||
| **Настройка** | Создаются в разделе «Настройки» | Зарегистрировать клиента, реализовать поток |
|
||
| **Контекст пользователя** | Отсутствует (уровень рабочей области) | Права конкретного пользователя |
|
||
| **Лучше всего подходит для** | Скрипты, внутренние инструменты | Внешние приложения, мультипользовательские интеграции |
|
||
| **Ротация токенов** | Вручную | Автоматическая с помощью refresh-токенов |
|
||
| **Доступ по областям действия** | Полный доступ к API | Детализированный через области действия |
|