Правильная аутентификация в CLI: полный гид по всем 4 методам
4 ключевых метода аутентификации в CLI, как их реализуют GitHub, AWS и AI-инструменты, а также ошибки безопасности, которых стоит избегать.
Каждый CLI для разработчиков предоставляет команду login как первую. И каждый реализует аутентификацию по-своему.
GitHub показывает код и открывает браузер для его подтверждения. AWS тоже открывает браузер, используя SSO на основе PKCE. В Stripe вы подтверждаете пару кодов в панели управления. Новые AI-инструменты (Claude Code, OpenAI Codex CLI, Cursor) также выбрали свой вариант.
Если ты пишешь CLI, аутентификация — одна из первых проблем, которые нужно решить. Выберешь не тот метод — услышишь об этом: раздражённые пользователи, проверки безопасности, а то и вместе. И на фоне нынешней волны AI-код-агентов, к оторые вызывают CLI программно, ставки выше: теперь ты аутентифицируешь уже не только человека. Возможно, ты передаёшь учётные данные автономному процессу.
Вот четыре метода аутентификации, которые действительно важны, как их реализуют крупнейшие инструменты и каких ошибок стоит избегать.
Четыре метода — кратко
Перед тем как погружаться в детали — краткое сравнение:
| Метод | Кому подходит | Безопасность | Требует браузер? |
|---|---|---|---|
| OAuth Device Code Flow | Безголовые среды, SSH | Высокая | Нет (на той же машине) |
| OAuth через браузер (redirect на localhost) | Локальная разработка | Наивысшая | Да |
| API-ключи / PAT | Автоматизация, CI/CD, быстрый прототип | Средняя | Нет |
| Client Credentials | Межмашинные сервисы | Высокая | Нет |
У каждого метода есть плюсы и минусы. Вот, что стоит знать о каждом из них.
1. OAuth Device Code Flow (RFC 8628)
Это тот метод, когда CLI показывает код типа ABCD-1234 и URL, а затем просит открыть его на любом устройстве и ввести код.
Кто использует: GitHub CLI (по умолчанию), Azure CLI (через --use-device-code), Vercel CLI (недавно перешёл на этот метод по умолчанию), OpenAI Codex CLI (в бета-режиме)
Как работает
- Ты запускаешь
cli login - CLI запрашивает у сервера авторизации device code, отправляя свой
client_idи нужные scopes - Сервер возвращает три значения:
device_code(внутренний идентификатор),user_code(короткий код, который ты вводишь), иverification_uri(куда идти) - CLI показывает код и URL, а затем начинает опрашивать сервер авторизации каждые 5+ секунд
- Ты открываешь URL на любом устройстве (телефон, ноутбук, другой компьютер), вводишь код и проходишь любую доступную аутентификацию (пароль, SSO, passkeys, MFA)
- После подтверждения, следующий запрос получает access token и refresh token
- CLI сохраняет их, готово
Почему разработчики любят этот метод
Главное преимущество — работает везде. SSH на удалённый сервер? Работает. В контейнере Docker? Работает. В облачной IDE, где нет локального браузера? Тоже работает. Браузер не должен быть на той же машине, что CLI.
Поддерживает весь спектр корпоративной аутентификации (SAML, OIDC, MFA), потому что всё происходит в браузере, а не в терминале. CLI никогда не видит твой пароль.
Ловушка безопасности, которую часто игнорируют
Device code flow — уязвим для фишинга. Атакующий может инициировать запрос device code, получить легитимный user code и обманом заставить тебя ввести его, по сути авторизуя сессию злоумышленника. Это не теория — исследователи демонстрировали такую атаку против AWS SSO с device code.
Это настолько серьёзно, что AWS изменила свой дефолт. С AWS CLI v2.22.0 значение по умолчанию для aws sso login изменилось с device code на PKCE (authorization code flow). Device code всё ещё доступен через --use-device-code, но это уже не основной путь.
В то же время у Microsoft начали полностью блокировать device code flow через политики conditional access — прямой сигнал, что этот метод считается высокорисковым.
В итоге ситуация интересная: Vercel ввёл device code flow как дефолт в сентябре 2025, а AWS — отказались от него. Логика такая: device code flow хорош там, где открыть браузер действительно нельзя, но если можно — PKCE надёжнее.
Со стороны провайдеров востребованность растёт. Logto только что добавили поддержку OAuth 2.0 Device Authorization Grant для нативных приложений (v1.38.0, open source) и Logto Cloud — теперь можно включить device flow для любого нативного приложения. Это важно, если ты строишь CLI. Реализовать RFC 8628 правильно (истечение срока действия кода, ограничение частоты запросов, polling, UX страницы верификации) — больше работы, чем большинство команд ожидает, и когда этим занимается auth-провайдер, тебе остаётся просто делать правильные HTTP-запросы.
Технические детали (RFC)
Несколько важных моментов из RFC 8628:
- Значение
expires_indevice-кодов задаётся сервером. RFC приводит 1800 секунд (30 минут) как пример, но это не обязательно. - Если сервер не указывает
intervalдля polling, по умолчанию клиент должен опрашивать раз в 5 секунд. - При ошибке
slow_downнужно добавить 5 секунд к интервалу. - Device code должен быть одноразовым и быстро истекать.
- Все обмены токенами только по HTTPS.
2. OAuth чере з браузер (redirect на localhost)
Самый распространённый метод для CLI на локальных машинах: запускаешь login, открывается браузер, проходишь аутентификацию, затем браузер редиректит обратно в локальный сервер (CLI временно поднимает его). Современные реализации добавляют PKCE (произносится как "пикси"), что существенно повышает стойкость схемы.
Кто использует: Claude Code, gcloud CLI, Terraform CLI, AWS CLI v2.22+ (SSO, по умолчанию PKCE)
Как работает
- Запускаешь
cli login - CLI стартует временный HTTP-сервер на случайном локальном порту (например,
http://127.0.0.1:8742) - Открывает твою дефолтную браузер к точке авторизации провайдера, в качестве redirect URI передаёт localhost-URL
- Проходишь аутентификацию в браузере (SSO/пароль/passkeys/что поддерживает провайдер)
- Провайдер редиректит браузер на
http://127.0.0.1:8742/callback?code=XXXX&state=YYYY - Локальный сервер забирает authorization code, обменивает его на токены через back-channel HTTPS
- Браузер показывает "Успех! Таб можно закрыть."
- CLI сохраняет токены и завершает работу локального сервера
Для пользователя UX максимально гладкий. Не надо копировать коды или вводить URL руками — просто открылся таб, автоматически закрылся.
Когда этот метод не работает
Требуется возможность открыть браузер и забиндиться на localhost. Значит, непригоден при:
- SSH-сессиях на удаленные серверы
- В Docker-контейнерах (если не делать port-forwarding)
- В CI/CD 'tenvironments
- На headless-серверах
- В некоторых закрытых корпоративных средах
Поэтому большинство инструментов с браузерным OAuth реализуют fallback — обычно device code flow или API-ключи.
Три ошибки безопасности, которые повторяются
Ошибка 1: Бинд на 0.0.0.0 вместо 127.0.0.1
Классическая, очень опасная. Если callback-сервер слушает все интерфейсы, любой на той же сети может перехватить authorization code.
Я видел это в продакшн-инструментах. Легко ошибиться, ведь многие HTTP-библиотеки по дефолту слушают 0.0.0.0.
Ошибка 2: Нет проверки параметра state
Параметр state — твоя CSRF-защита. Если его не проверить, злоумышленник может подсунуть твой CLI авторизационный код из чужой сессии.
Ошибка 3: Отсутствует PKCE
Если не использовать PKCE (Proof Key for Code Exchange), код авторизации легко перехватить и переиграть.
В классическом OAuth Authorization Code Flow, если злоумышленник перехватит authorization code (по сети, прочитав redirect-URL), он сможет обменять его на токены. PKCE защищает: обменять code на токен сможет только кто знает изначальный code_verifier.
Как работает PKCE:
- CLI генерирует случайный
code_verifier(строка высокой энтропии) - Создаёт
code_challenge— SHA-256 хеш от verifier - С вызовом авторизации challenge уходит серверу
- При обмене code на токен CLI отправляет изначальный
code_verifier - Сервер проверяет соответствие verifier — challenge
Злоумышленник не знает code_verifier — не получит токен.
Поэтому AWS CLI v2.22+ сделал PKCE дефолтом для SSO, отказавшись от device code flow. Когда CLI может открыть браузер на той же машине — браузерный OAuth с PKCE всегда лучше: тот же UX, но жёстче безопасность, без риска фишинга. Device code flow остаётся актуальным для "headless"-сценариев, но для локальной разработки он всё реже нужен.
3. API-ключи и личные токены доступа
Самый простой вариант. Сгенерируй токен на сайте, вставь в конфиг или env-переменную — готово.
Кто использует: Stripe CLI (одна из опций входа), npm, pip, большинство AI-код-агентов как запасной вариант (Claude Code через ANTHROPIC_API_KEY, OpenAI — через OPENAI_API_KEY, Aider)
Как работает
- Входишь в веб-панель сервиса
- Settings → API keys (или personal access tokens, developer tokens)
- Генерируешь новый ключ (например,
sk_live_,ghp_,npm_) - Сохраняешь в файл конфига (
~/.config/stripe/config.toml,~/.aws/credentials) или env-переменную
CLI читает это при запуске и отправляет в заголовке Authorization как Bearer-токен.
Почему API-ключи всё ещё популярны (несмотря на риски)
Для автоматизации API-ключи вне конкуренции. Работают в CI/CD, контейнерах, скриптах, cron. Любое окружение, где можно прочитать env-переменную. Браузер не нужен. Нет интерактивных запросов. Нет пляски с обновлением токена.
Особенно для AI-агентов — API-key проще всего интегрировать. Когда Claude Code или Cursor вызывают API — проще всего прокинуть env-переменную с ключём.
Риски настоящие
- Утечки. Ключи часто попадают в git-коммиты, логи, error messages, CI-выводы. GitHub сканирует токены и ежегодно обнаруживает более миллиона утечек.
- Избыточные права. Большинство ключей имеют слишком высокий уровень доступа. При утечке последствия большие.
- Нет MFA. API-ключи обходят твою сложную настройку многофакторной аутентификации.
- Сложно менять. Повернул ключ — теперь обновлять везде где он есть. С командой — организационная проблема.
Современное улучшение: временные токены
Лучше всего, если возможно, использовать обмен ключа на краткоживущий токен.
AWS наладил это с помощью STS (Security Token Service). Долгоживущие креды используются только чтобы получить временные, живущие час. aws-vault автоматизирует этот процесс.
Даже если начал с API-ключей — попробуй добавить обмен на временные. Так окно риска при утечке — "до тех пор, пока не заметят" — превращается в "один час".
4. Client Credentials Flow
Этот OAuth 2.0 flow для межсервисной аутентификации: сервис говорит с сервисом, человека нет.
Используется для: CI/CD, фоновые сервисы, автоматизированные инструменты
Как работает
Сервис отправляет свой client_id и client_secret напрямую серверу auth, получает обратно краткоживущий access token. Нет браузера, нет взаимодействия, нет redirect.
Когда использовать
Используй client credentials если:
- Подключается сервис или бот, не человек
- Ты в CI/CD pipeline
- Нужно автоматизировать, без вмешательства человека
- "Пользователь" — само приложение
Нельзя использовать для людей — нет MFA, SSO, интерактива.
Каки е методы используют реальные CLI
Вот актуальная сводка (основываясь на документации и исходниках). Во многих статьях инфа устаревшая — инструменты быстро меняют дефолты.
| CLI-инструмент | Метод по умолчанию | Запасные варианты | Где токены |
|---|---|---|---|
GitHub CLI (gh) | Device code flow через браузер | PAT (--with-token), env (GH_TOKEN) | OS keychain (ещё: plaintext-файл) |
| AWS CLI v2 | PKCE auth code flow (SSO) | Device code (--use-device-code), credential files | ~/.aws/sso/cache/ |
Azure CLI (az) | WAM на Windows; браузерный flow на Linux/macOS | Device code (--use-device-code) | ~/.azure/msal_token_cache.* |
| Vercel CLI | Device code flow (дефолт, сентябрь 2025) | API token (--token, env) | ~/.local/share/com.vercel.cli/auth.json |
| Stripe CLI | Браузерное pairing | API key (--interactive, --api-key, или env) | ~/.config/stripe/config.toml |
| gcloud CLI | OAuth через браузер | --no-browser ручной flow | ~/.config/gcloud/ |
| Claude Code | OAuth через браузер | API key (env, apiKeyHelper) | OS keychain / ~/.claude/.credentials.json |
| OpenAI Codex CLI | OAuth через браузер | Device code (beta), API key | ~/.codex/auth.json / OS keyring |
| Terraform CLI | OAuth через браузер | Ввод токена | ~/.terraform.d/credentials.tfrc.json |
Тренд очевиден: для локальной разработки дефолт — OAuth через браузер; device code flow — fallback для "headless", API-ключи — для автоматизации. PKCE становится стандартом для высокой безопасности, если браузер доступен.
Где хранить токены: что стоит и чего избегать
Безопасная аутентификация не имеет смысла, если токены хранятся плохо.
Как надо: OS keychains
Все крупные ОС имеют встроенное шифрованное хранилище учётных данных:
- macOS: Keychain (используется GitHub CLI, Claude Code)
- Windows: Credential Manager
- Linux: Secret Service API (GNOME Keyring, KDE Wallet)
Это обеспечивает шифрование, контроль доступа, поддержку аппаратной безопасности. CLI не надо реализовывать свою криптографию.
Fallback: зашифрованные файлы с ограниченными правами
Если keychain недоступен (контейнеры, минимальные сборки Linux) — используй шифрованные файлы-конфиги только с owner'ом:
Чего избегать
Открытые текстовые файлы. Казалось бы очевидно — но многие до сих пор так делают. Открытый токен-файл доступен любому процессу от твоего имени, любому бэкапу, и любому, кто временно получил доступ к машине.
Env-переменные для долгого хранения. Env-переменные видны через ps, могут быть залогированы или унаследованы subprocess-ами. Для CI/CD подойдёт (секреты управляются платформой CI) — но для локальной разработки рискованно.
Браузерный localStorage. Если CLI есть web-фронт — не храни токены в localStorage. Любой XSS — и всё украдут.
Управление жизненным циклом токенов
Access tokens
Они должны быть короткоживущими: 1 час — стандарт. После истечения CLI должен автоматически обновлять токен, пользователь не должен повторно логиниться ради обычной работы.
Refresh tokens
Refresh-токены — длинноживущие креды, которые позволяют получать новые access token без повторной аутентификации. Самые ценные с точки зрения атаки — потому что живут от дней до месяцев.
Ротация refresh токенов
Современные auth-системы вращают refresh-токен на каждый запрос:
- CLI отправляет refresh-токен чтобы получить новый access-token
- Сервер возвращает новый access token и новый refresh-token
- Старый refresh-токен сразу инвалидируется
- CLI сохраняет оба новых токена
Это минимизирует риск. Если злоумышленник попробует воспользоваться уже использованным refresh-токеном — сервер обнаружит reuse и инвалидирует всю токен-семью. И у пользователя, и у злоумышленника отберут доступ — надо заново залогиниться, зато злоумышленник не сможет удерживать доступ.
Частые ошибки (с примерами)
1. Callback-server слушает все интерфейсы
Уже упоминалось выше, повторю: всегда bind'ить к 127.0.0.1, никогда — 0.0.0.0.
2. Логи руются токены
Такое случается чаще, чем признаются. Debug-лог, error handler с дампом заголовков, verbose mode …
3. Запекание учётки в Docker-образ
Docker-образ — не хранилище секретов. Каждый слой можно извлечь.
4. Не происходит graceful-обновления токена
Если токен истекает в процессе операции — не надо падать с 401 ошибкой. Попытайся обновить, и только если refresh-токен тоже истёк, проси новый login.
5. Игнорирование principle of least privilege
Не проси scope admin:*, когда тебе нужен только repo:read. Это касается и OAuth, и API-ключей.
Если AI-агент использует CLI, это особенно важно: скорее всего, не нужно давать боту права на удаление репозиториев, если требуется только чтение кода.
Сложности с AI-агентами
Чем 2026 год отличается от 2023: CLI теперь используют не только люди. AI-агенты типа Claude Code, Codex, Cursor-агент запускают CLI программно. Это вызывает новые задачи в плане аутентификации:
Делегирование прав. Если Claude Code запускает gh pr create от твоего имени, он пользуется твоими кредами GitHub. Но действительно ли AI-агент должен иметь тот же доступ, что и ты? Principle of least privilege говорит "нет", но мало где можно уменьшить права агента.
Экспозиция учёток. Если API-ключ — env-переменная, любой процесс может её прочитать, включая subprocess агента. Claude Code уже предлагает скрипты apiKeyHelper, которые генерируют короткоживущие токены по запросу, но это пока не станд арт.
Headless-аутентификация для агентов. Если AI-агент в sandbox'е, браузер не откроет. Device code flow подходит (человек подтверждает на отдельном устройстве), но обычно проще прокинуть API-ключ (не требует взаимодействия).
Audit-trail. Если AI-агент делал вызовы с твоими кредами, логи будут считать, что это был ты. Сейчас нет стандарта отличать "человек сделал" от "агент сделал за человека".
Эта тема ещё развивается. Лучшее, что можно сделать сейчас:
- Использовать токены с минимальным scope для агентов
- Предпочитать краткоживущие креды (временные токены вместо постоянных API-ключей)
- Делить учётки для агентов и людей
- Мониторить вызовы API на аномалии
Как выбрать метод аутентификации
Если выбираешь метод, вот сокращённая версия:
"Пользователи — разработчики на локальных машинах" → OAuth через браузер + PKCE (лучше всего по безопасности и удобству)
"CLI нужен для SSH/в контейнере" → Device code flow как fallback, browser OAuth — основной
"CI/CD, без человека в цикле" → Client credentials flow или scope API-ключи
"Нужна максимально быстрая интеграция" → API-ключи (но добавь потом ротацию токенов)
"Корпоративные клиенты с SSO и MFA" → Любой OAuth (device code или browser), поддерживающий enterprise-auth stack
"CLI будут использовать AI-агенты" → Дай поддержку API-ключей (для агентов) + OAuth (для людей) + scope + краткоживущие токены
FAQ
Device code flow — безопасно ли это?
В основном, да. Но есть известный риск фишинга: злоумышленник может инициировать device code и подловить пользователя ввести его. Поэтому AWS перевели по умолчанию на PKCE для SSO. Для headless-сред — device code всё ещё лучшее решение, но риск фишинга есть.
Можно хранить токены в переменных окружения?
В CI/CD — да: платформа CI шифрует их на диске и подставляет во время запуска. Для локальной разработки — нет: лучше использовать OS keychain. Env-переменные видны в process listing, могут случайно попасть в логи или утечь в subprocess.
Чем отличается API key от personal access token?
По сути — почти ничем. Оба это креды для авторизации в API. Разница в организации: API-ключи обычно относятся к проекту или приложению, personal access — к аккаунту пользователя. Иногда сервисы называют их одинаково.
Как часто менять креды?
Access-токены: каждый час (автоматически через refresh flow). Refresh-токены: вращать при каждом использовании (это должен делать auth-сервер). API-ключи: не реже, чем раз в 90 дней, либо сразу при подозрении на утечку. В реальности API-ключи редко вращаются вовремя — и это плохо.
Как быть с аутентификацией в контейнерах Docker?
Три варианта, по приоритету:
- Device code flow для интерактивной работы (браузер можно открыть на другой машине)
- Env-переменные, передаваемые во время запуска (
docker run -e API_KEY=${API_KEY}), для CI/CD - Volume-mounted креды (
docker run -v ~/.config/tool:/root/.config/tool:ro) для локального использования
Никогда не запекай креды в image. Никогда.
А как же аутентификация MCP (Model Context Protocol)?
MCP — новый стандарт для AI-агентов, которые будут обращаться к внешним сервисам. Возникает новая задача: агенту нужны креды для MCP-сервера, а тому — для downstream API. Стандарт только формируется. Пока все передают API-ключи или OAuth-токены через конфиг MCP. Ожидай быстрых изменений.
CLI-аутентификация стремительно меняется. То, что было best practice всего пару лет назад (device code flow по дефолту, открытые credential-файлы), уже уступает место новому. Если добавляешь auth в CLI сейчас — начинай с OAuth + PKCE для людей, API-ключей для автоматизации, и помни: скоро твои главные пользователи — AI-агенты.

