OAuth PKCE
Авторизация пользователей и получение API-ключей через OAuth 2.0 PKCE flow
OAuth PKCE
OAuth PKCE позволяет сторонним приложениям получать API-ключи от имени пользователей usellm, без ручного создания ключей. Пользователь авторизует приложение через consent screen, выбирает организацию, scopes и лимиты расходов, после чего приложение получает готовый API-ключ.
Если вы просто хотите использовать API напрямую, создайте ключ в личном кабинете. OAuth PKCE нужен разработчикам сторонних приложений, которые запрашивают доступ у пользователей.
Как это работает
- Генерация PKCE: приложение генерирует пару
code_verifier+code_challenge(SHA-256). - Перенаправление на авторизацию: приложение перенаправляет пользователя на
https://api.usellm.ru/auth/authorizeс параметрами. - Consent screen: пользователь видит экран подтверждения и выбирает организацию, разрешённые данные и лимит расходов.
- Callback с кодом: после подтверждения пользователь перенаправляется обратно на
callback_urlс параметромcode. - Обмен кода на API-ключ: приложение обменивает
code+code_verifierна API-ключ черезPOST /auth/token.
Шаг 1: Генерация PKCE
Сгенерируйте случайный code_verifier (43-128 символов, [A-Za-z0-9\-._~]) и вычислите code_challenge как BASE64URL(SHA256(code_verifier)).
# Генерация code_verifier
CODE_VERIFIER=$(openssl rand -base64 32 | tr -d '=' | tr '+/' '-_')
# Вычисление code_challenge (S256)
CODE_CHALLENGE=$(echo -n "$CODE_VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr -d '=' | tr '+/' '-_')
Сохраните code_verifier: он понадобится на шаге обмена кода. Никогда не передавайте его в URL или в открытом виде.
Шаг 2: Перенаправление на авторизацию
Перенаправьте пользователя на эндпоинт авторизации с необходимыми параметрами:
| Параметр | Обязательный | Описание |
|---|---|---|
response_type | да | Всегда code |
callback_url | да | URL для редиректа после авторизации (HTTPS, исключение: localhost) |
code_challenge | да | BASE64URL(SHA256(code_verifier)), 43-128 символов |
code_challenge_method | да | Всегда S256 |
state | нет | Произвольная строка для CSRF-защиты (возвращается без изменений) |
app_name | нет | Название приложения (отображается на consent screen) |
# URL для перенаправления пользователя
echo "https://api.usellm.ru/auth/authorize?\
response_type=code&\
callback_url=https://example.com/callback&\
code_challenge=$CODE_CHALLENGE&\
code_challenge_method=S256&\
state=random-csrf-string&\
app_name=My+App"
Шаг 3: Обработка callback
После авторизации пользователь будет перенаправлен на ваш callback_url с параметрами:
- При успехе:
?code=<код_авторизации>&state=<ваш_state> - При отказе:
?error=access_denied&state=<ваш_state>
// На вашей callback-странице
const url = new URL(window.location.href)
const code = url.searchParams.get('code')
const state = url.searchParams.get('state')
const error = url.searchParams.get('error')
if (error) {
console.error('Пользователь отклонил авторизацию:', error)
}
else if (code) {
// Проверьте state для защиты от CSRF
// Переходите к шагу 4 — обмен кода на ключ
}
Шаг 4: Обмен кода на API-ключ
Обменяйте код авторизации на API-ключ, отправив code_verifier для подтверждения PKCE:
curl -X POST "https://api.usellm.ru/auth/token" \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"code": "полученный-код",
"code_verifier": "ваш-code-verifier",
"callback_url": "https://example.com/callback"
}'
Ответ:
{
"key": "usl_abc123...",
"user_id": "usr_123"
}
Параметр callback_url в запросе должен точно совпадать с тем, что был указан при авторизации.
Шаг 5: Использование API-ключа
Полученный ключ работает как обычный API-ключ usellm:
curl -X POST "https://api.usellm.ru/v1/chat/completions" \
-H "Authorization: Bearer usl_abc123..." \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-6-astra",
"messages": [{"role": "user", "content": "Привет!"}]
}'
Данные пользователя
Получите информацию о пользователе, авторизовавшем ключ, через эндпоинт GET /auth/userinfo:
curl -H "Authorization: Bearer usl_abc123..." \
"https://api.usellm.ru/auth/userinfo"
Ответ зависит от scopes, разрешённых пользователем:
{
"user_id": "usr_123",
"email": "user@example.com",
"organization": {
"id": "org_456",
"name": "Моя организация"
}
}