• cli
  • oauth
  • безопасность
  • ai-инструменты

Правильная аутентификация в CLI: полный гид по всем 4 методам

4 ключевых метода аутентификации в CLI, как их реализуют GitHub, AWS и AI-инструменты, а также ошибки безопасности, которых стоит избегать.

Yijun
Yijun
Developer

Хватит тратить недели на аутентификацию пользователей
Запускайте безопасные приложения быстрее с Logto. Интегрируйте аутентификацию пользователей за считанные минуты и сосредоточьтесь на вашем основном продукте.
Начать
Product screenshot

Каждый 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 (в бета-режиме)

Как работает

  1. Ты запускаешь cli login
  2. CLI запрашивает у сервера авторизации device code, отправляя свой client_id и нужные scopes
  3. Сервер возвращает три значения: device_code (внутренний идентификатор), user_code (короткий код, который ты вводишь), и verification_uri (куда идти)
  4. CLI показывает код и URL, а затем начинает опрашивать сервер авторизации каждые 5+ секунд
  5. Ты открываешь URL на любом устройстве (телефон, ноутбук, другой компьютер), вводишь код и проходишь любую доступную аутентификацию (пароль, SSO, passkeys, MFA)
  6. После подтверждения, следующий запрос получает access token и refresh token
  7. 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_in device-кодов задаётся сервером. 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)

Как работает

  1. Запускаешь cli login
  2. CLI стартует временный HTTP-сервер на случайном локальном порту (например, http://127.0.0.1:8742)
  3. Открывает твою дефолтную браузер к точке авторизации провайдера, в качестве redirect URI передаёт localhost-URL
  4. Проходишь аутентификацию в браузере (SSO/пароль/passkeys/что поддерживает провайдер)
  5. Провайдер редиректит браузер на http://127.0.0.1:8742/callback?code=XXXX&state=YYYY
  6. Локальный сервер забирает authorization code, обменивает его на токены через back-channel HTTPS
  7. Браузер показывает "Успех! Таб можно закрыть."
  8. 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:

  1. CLI генерирует случайный code_verifier (строка высокой энтропии)
  2. Создаёт code_challenge — SHA-256 хеш от verifier
  3. С вызовом авторизации challenge уходит серверу
  4. При обмене code на токен CLI отправляет изначальный code_verifier
  5. Сервер проверяет соответствие 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)

Как работает

  1. Входишь в веб-панель сервиса
  2. Settings → API keys (или personal access tokens, developer tokens)
  3. Генерируешь новый ключ (например, sk_live_, ghp_, npm_)
  4. Сохраняешь в файл конфига (~/.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 v2PKCE auth code flow (SSO)Device code (--use-device-code), credential files~/.aws/sso/cache/
Azure CLI (az)WAM на Windows; браузерный flow на Linux/macOSDevice code (--use-device-code)~/.azure/msal_token_cache.*
Vercel CLIDevice code flow (дефолт, сентябрь 2025)API token (--token, env)~/.local/share/com.vercel.cli/auth.json
Stripe CLIБраузерное pairingAPI key (--interactive, --api-key, или env)~/.config/stripe/config.toml
gcloud CLIOAuth через браузер--no-browser ручной flow~/.config/gcloud/
Claude CodeOAuth через браузерAPI key (env, apiKeyHelper)OS keychain / ~/.claude/.credentials.json
OpenAI Codex CLIOAuth через браузерDevice code (beta), API key~/.codex/auth.json / OS keyring
Terraform CLIOAuth через браузерВвод токена~/.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-токен на каждый запрос:

  1. CLI отправляет refresh-токен чтобы получить новый access-token
  2. Сервер возвращает новый access token и новый refresh-token
  3. Старый refresh-токен сразу инвалидируется
  4. 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?

Три варианта, по приоритету:

  1. Device code flow для интерактивной работы (браузер можно открыть на другой машине)
  2. Env-переменные, передаваемые во время запуска (docker run -e API_KEY=${API_KEY}), для CI/CD
  3. 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-агенты.