Cómo hacer bien la autenticación en la CLI: la guía completa de los 4 métodos
Los 4 métodos de autenticación en CLI que importan, cómo los implementan GitHub, AWS y herramientas de IA, y los errores de seguridad que querrás evitar.
Cada CLI para desarrolladores incluye login como su primer comando. Y cada una resuelve la autenticación de manera diferente.
GitHub te muestra un código y abre tu navegador para verificarlo. AWS abre el navegador para un SSO basado en PKCE. Stripe te pide confirmar un código de emparejamiento en el panel. Las herramientas de IA más nuevas (Claude Code, OpenAI Codex CLI, Cursor) también eligieron cada una su propio enfoque.
Si estás creando una CLI, la autenticación será de las primeras cosas que tendrás que definir. Si eliges el método incorrecto, lo notarás: usuarios frustrados, auditorías de seguridad, o ambos. Y con la reciente ola de agentes de codificación de IA que llaman a herramientas CLI de forma programática, el riesgo aumenta: ya no solo autenticas a un humano. Podrías estar entregando credenciales a un proceso autónomo.
Aquí están los cuatro métodos de autenticación que importan, cómo los implementan las herramientas más grandes y los errores que debes evitar.
Los cuatro métodos de un vistazo
Antes de entrar en detalles, aquí va una comparación rápida:
| Método | Mejor para | Seguridad | ¿Requiere navegador? |
|---|---|---|---|
| OAuth Device Code Flow | Entornos sin cabeza, SSH | Alta | No (en la misma máquina) |
| OAuth basado en navegador (redirect a localhost) | Desarrollo local | Máxima | Sí |
| Claves API / PATs | Automatización, CI/CD, prototipado rápido | Moderada | No |
| Credenciales de cliente | De máquina a máquina, servicios | Alta | No |
Cada uno tiene pros y contras. Esto es lo que tienes que saber de cada uno.
1. OAuth device code flow (RFC 8628)
Este es el que tu CLI te muestra un código como ABCD-1234 y una URL, y luego te pide abrir esa URL en cualquier dispositivo e ingresar el código.
Quién lo usa: GitHub CLI (por defecto), Azure CLI (vía --use-device-code), Vercel CLI (recientemente cambió a esto como predeterminado), OpenAI Codex CLI (como opción beta)
Cómo funciona
- Ejecutas
cli login - La CLI solicita un código de dispositivo al servidor de autenticación, enviando su
client_idy los permisos solicitados - El servidor devuelve tres cosas: un
device_code(identificador interno), unuser_code(el código corto que ingresas), y unverification_uri(dónde ir) - Tu CLI muestra el código y la URL, luego empieza a hacer polling al servidor de autenticación cada 5+ segundos
- Abres la URL en cualquier dispositivo (teléfono, portátil, otra computadora), escribes el código y te autenticas como quieras (contraseña, SSO, passkeys, MFA)
- Una vez aprobado, el siguiente polling devuelve un access token y refresh token
- La CLI almacena estos y ya tienes acceso
Por qué a los desarrolladores les gusta
Su mayor ventaja: funciona en todos lados. ¿SSH a un servidor remoto? Funciona. ¿Ejecutas dentro de un contenedor Docker? Funciona. ¿IDE en la nube sin navegador local? Funciona. El navegador no tiene que estar en la misma máquina que la CLI.
Además, soporta toda la gama de métodos empresariales (SAML, OIDC, MFA) porque todo pasa en el navegador, no en el terminal. La CLI nunca ve tu contraseña.
El problema de seguridad que muchos pasan por alto
El device code flow tiene un problema de phishing. Un atacante puede iniciar una solicitud de código de dispositivo, obtener un código legítimo e inducirte a ingresarlo, autorizando así la sesión del atacante. Esto no es teórico. Investigadores han documentado este ataque contra AWS SSO.
Esto es suficientemente grave que AWS cambió su predeterminado. A partir de AWS CLI v2.22.0, el default para aws sso login pasó de device code flow a autorización basada en código PKCE. Device code sigue disponible por --use-device-code, pero ya no es la vía principal.
Mientras tanto, el tenant propio de Microsoft ha empezado a bloquear por completo device code flow vía políticas de acceso condicional, señal clara de que lo consideran de alto riesgo.
Así que hay cierta división: Vercel adoptó device code flow como su default en septiembre de 2025, mientras AWS se alejó de él. El patrón es: device code flow es genial donde de verdad no puedes abrir un navegador, pero si lo puedes abrir local, PKCE es más seguro.
Por el lado de los proveedores, la demanda claramente crece. Logto acaba de lanzar soporte para Device Authorization Grant de OAuth 2.0 para apps nativas en v1.38.0 (código abierto) y Logto Cloud, así que ya puedes habilitarlo como método de autorización para cualquier app nativa. Esto importa si construyes una CLI. Implementar correctamente RFC 8628 (expiración, rate limit, lógica de polling y UX de la página de verificación) requiere más trabajo de lo que la mayoría espera, así que si tu proveedor lo maneja, solo tienes que hacer las llamadas HTTP correctas.
Detalles técnicos del RFC
Algunos puntos clave del RFC 8628:
- El valor de
expires_inpara device codes lo pone el auth server. El RFC usa 1800 segundos (30 minutos) como ejemplo, pero no es fijo. - Si el server no especifica
intervalde polling, los clientes deben usar por defecto 5 segundos. - Si recibes un error
slow_down, añade 5 segundos al intervalo. - Los device codes deben ser de un solo uso y tener caducidad corta.
- Todos los intercambios de tokens deben pasar por HTTPS.
2. OAuth basado en navegador (redirect a localhost)
Este es el método más común para CLIs en la máquina local de un desarrollador. Ejecutas login, tu navegador se abre, te autenticas y el navegador redirige de vuelta a un servidor local que levantó la CLI. Las implementaciones modernas agregan PKCE (pronunciado "pixie") encima, que dificulta su explotación.
Quién lo usa: Claude Code, gcloud CLI, Terraform CLI, AWS CLI v2.22+ (para SSO, PKCE es por defecto)
Cómo funciona
- Ejecutas
cli login - La CLI inicia un servidor HTTP temporal en un puerto local aleatorio (por ejemplo
http://127.0.0.1:8742) - Abre tu navegador por defecto con la URL de autorización del proveedor, pasando ese localhost como redirect URI
- Te autenticas en el navegador (SSO, contraseña, passkeys o lo que soporte el proveedor)
- El proveedor redirige el navegador a
http://127.0.0.1:8742/callback?code=XXXX&state=YYYY - El servidor local captura el código de autorización y lo intercambia por tokens vía HTTPS
- El navegador muestra "¡Éxito! Puedes cerrar esta pestaña"
- La CLI guarda los tokens y apaga el servidor
La experiencia es fluida. Sin copiar códigos, ni teclear URLs. Solo se abre y se cierra una pestaña.
Cuando no sirve
Esto solo funciona cuando la CLI puede abrir un navegador y enlazarse a localhost. Eso descarta:
- Sesiones SSH a servidores remotos
- Contenedores Docker (salvo con port forwarding)
- Pipelines CI/CD
- Servidores sin cabeza
- Algunos entornos empresariales restringidos
Por esto, la mayoría de las herramientas que usan browser OAuth también soportan un fallback (usualmente device code flow o claves API).
Tres fallos de seguridad recurrentes
Fallo 1: Atar el servidor de callback a 0.0.0.0 en vez de 127.0.0.1
El error más común y grave. Si tu servidor escucha todas las interfaces, cualquiera en la red puede interceptar el código de autorización.
Lo he visto en CLIs en producción. Es un error fácil porque muchas librerías server HTTP usan 0.0.0.0 por defecto.
Fallo 2: No validar el parámetro state
El parámetro state es tu protección CSRF. Sin él, un atacante puede hacer que tu CLI acepte códigos de una sesión maliciosa.
Fallo 3: No usar PKCE
Si tu flujo OAuth no usa PKCE (Proof Key for Code Exchange), el código de autorización puede interceptarse y ser reutilizado.
En el authorization code flow estándar, si un atacante intercepta el código (ya sea por red o leyendo la URL), puede canjearlo por tokens. PKCE previene esto exigiendo prueba de que la petición de token viene del mismo cliente que inició la autorización.
Esto añade PKCE al flujo:
- Antes del flujo, la CLI genera un
code_verifieraleatorio (string de alta entropía) - Crea un
code_challengehasheando el verifier por SHA-256 - El challenge se manda con la autorización inicial
- Para canjear el código, se envía el
code_verifieroriginal - El auth server verifica que coincidan
Un atacante que intercepte el código no tiene el verifier, no puede completar el canje.
Por esto AWS CLI v2.22+ hizo PKCE el default para SSO, dejando atrás device code flow. Si la CLI puede abrir navegador en la misma máquina, browser OAuth con PKCE es siempre mejor — misma UX, garantías de seguridad más fuertes, sin vector de phishing. Device code flow es lo correcto si el navegador no puede estar en la misma máquina (SSH, contenedores, entornos remotos), pero eso no es lo usual para desarrollo local.
3. Claves API y tokens de acceso personal
El enfoque más simple. Generas un token en un panel web, lo pegas en el config de la CLI o una variable de entorno, ¡y listo!
Quién lo usa: Stripe CLI (como opción de login), npm, pip, la mayoría de herramientas de IA como fallback (Claude Code con ANTHROPIC_API_KEY, OpenAI con OPENAI_API_KEY, Aider)
Cómo funciona
- Inicia sesión en el panel web del servicio
- Ve a configuración → claves API (personal access tokens, developer tokens)
- Genera una nueva clave, normalmente una string larga y aleatoria con prefijo (
sk_live_,ghp_,npm_) - Guárdala en un archivo de configuración (
~/.config/stripe/config.toml,~/.aws/credentials) o una variable de entorno
La CLI la lee al iniciar y la manda en peticiones API como un token Bearer en la cabecera Authorization.
Por qué sigue siendo popular pese a los riesgos
Para automatización, las API keys son difíciles de superar. Funcionan en CI/CD, contenedores, scripts, cron jobs. Donde puedas leer una variable de entorno. Sin navegador. Sin prompts interactivos. Sin tokens de actualización.
Para los flujos de agentes AI, API keys es lo más práctico. Cuando Claude Code o Cursor necesitan llamar una API, una variable de entorno con una API key es lo más simple.
Los riesgos son reales
- Filtraciones. Las API keys terminan en commits de git, logs, mensajes de error y output de CI. GitHub detecta y reporta más de un millón de secretos expuestos por año.
- Sobre-permisos. La mayoría otorgan acceso amplio. Si se filtran, el impacto es alto.
- Sin MFA. Ignoran tu MFA configurado.
- Difíciles de rotar. Al rotar, debes cambiarla en todos los sitios donde se usa. Con equipos, es un dolor de coordinación.
Mejora moderna: intercambio por tokens temporales
Lo ideal con API keys: intercambiarlas por tokens de vida corta en tiempo de ejecución.
AWS innovó con STS (Security Token Service). Tus credenciales de larga duración solo se usan para pedir credenciales temporales que expiran en una hora. Herramientas como aws-vault automatizan esto.
Aunque empieces con API keys, agrega este patrón. Limita el daño de una clave comprometida de "hasta que lo notes" a "una hora".
4. Client credentials flow
Este flujo OAuth 2.0 está pensado para autenticación de máquina a máquina: servicios hablando entre sí, sin humanos involucrados.
Usado en: pipelines CI/CD, servicios en background, herramientas automáticas
Cómo funciona
El servicio envía su client_id y client_secret al servidor auth y recibe un access token de vida corta. Sin navegador, ni interacción, ni redirect.
Cuándo usarlo
Úsalo cuando:
- Un servicio o bot necesita autenticación, no un humano
- Estás en un pipeline CI/CD
- Requieres acceso automatizado, sin intervención
- El "usuario" es la aplicación misma
No lo uses para humanos. No soporta MFA, SSO ni nada interactivo.
Qué usan realmente los CLI
Aquí un desglose actualizado según documentación y código fuente. Muchos artículos lo reportan mal porque los defaults cambian seguido.
| Herramienta CLI | Auth por defecto | Fallbacks | Almacenamiento de tokens |
|---|---|---|---|
GitHub CLI (gh) | Device code via navegador | PAT (--with-token), var env (GH_TOKEN) | Llavero de SO (fallback: archivo plano) |
| AWS CLI v2 | PKCE auth code flow (SSO) | Device code (--use-device-code), archivos credenciales | ~/.aws/sso/cache/ |
Azure CLI (az) | WAM en Windows; browser auth en Linux/macOS | Device code (--use-device-code) | ~/.azure/msal_token_cache.* |
| Vercel CLI | Device code flow (por defecto, sep 2025) | Token API (--token, var env) | ~/.local/share/com.vercel.cli/auth.json |
| Stripe CLI | Flujo de emparejamiento por navegador | API key (--interactive, --api-key o var env) | ~/.config/stripe/config.toml |
| gcloud CLI | Browser OAuth | --no-browser manual | ~/.config/gcloud/ |
| Claude Code | Browser OAuth | API key (var env, apiKeyHelper) | Llaveros SO/ ~/.claude/.credentials.json |
| OpenAI Codex CLI | Browser OAuth | Device code (beta), API key | ~/.codex/auth.json / llavero SO |
| Terraform CLI | Browser OAuth | Pegar token | ~/.terraform.d/credentials.tfrc.json |
La tendencia es clara: browser-based OAuth es el default para desarrollo local, device code flow es el fallback para headless, y API keys para automatización. PKCE va ganando como la opción más segura cuando hay navegador.
Almacenamiento de tokens: qué usar y qué evitar
Hacer bien la autenticación no sirve si guardas mal los tokens.
Lo correcto: llaveros del SO
Cada SO principal tiene almacén cifrado integrado:
- macOS: Keychain (usado por GitHub CLI, Claude Code)
- Windows: Credential Manager
- Linux: Secret Service API (GNOME Keyring, KDE Wallet)
Dan cifrado a nivel SO, control de acceso e integración de hardware. No necesitas implementar cripto propia.
Fallback: archivos config cifrados
Si no tienes llavero (contenedores, Linux minimalista), usa archivos cifrados con permisos restringidos:
Qué evitar
Archivos en texto plano. Parece obvio pero muchos lo siguen haciendo. Un archivo de token plano es accesible por cualquier proceso de tu usuario, herramientas de backup, o cualquiera con acceso temporal a tu máquina.
Variables de entorno para almacenamiento a largo plazo. Las var env se ven en process listings, pueden ser logueadas por crash reporters y heredadas por procesos hijos. Está bien en CI/CD (el CI gestiona el secreto) pero es arriesgado en desarrollo local.
localStorage del navegador. Si tu CLI tiene componente web, no guardes tokens allí. Una XSS los expone todos.
Gestión del ciclo de vida de tokens
Access tokens
Mantenlos de vida corta. Una hora es el estándar. Al expirar, la CLI debe renovarlo en silencio. La persona no debería tener que hacer login de nuevo por operaciones normales.
Refresh tokens
Los refresh tokens permiten obtener nuevos access tokens sin reautenticación. Son valiosos para atacantes (duran días o meses).
Rotación de refresh tokens
Los sistemas modernos rotan refresh tokens en cada uso:
- La CLI manda refresh token para obtener nuevo access token
- El server devuelve nuevos access y refresh tokens
- El refresh token anterior se invalida de inmediato
- La CLI almacena ambos nuevos tokens
Esto reduce el daño si te roban un refresh token. Si un atacante usa uno ya usado por la CLI real, el server detecta el reuso e invalida toda la familia de tokens. Así tanto el token del atacante como el del usuario dejan de funcionar, forzando nuevo login y evitando el acceso del atacante.
Errores comunes (con código)
1. Atar el servidor callback a todas las interfaces
Ya lo cubrimos antes, pero repito: siempre usa 127.0.0.1, nunca 0.0.0.0.
2. Registrar tokens en logs
Sucede más de lo que piensas. Un log de debug, un error handler que imprime cabeceras, un modo verbose...
3. Meter credenciales en imágenes de contenedor
Las imágenes Docker no son almacenes de secretos. Cada capa es extraíble.
4. No manejar bien la expiración de tokens
Cuando un token expira durante una operación, no crashes con error 401. Intenta refrescar, y solo pide re-login si el refresh token también expiró.
5. Ignorar el principio de mínimo privilegio
No pidas scope admin:* si solo necesitas repo:read. Aplica tanto para scopes de OAuth como permisos de claves API.
Si un agente de IA usa tu CLI, esto es todavía más importante. Probablemente no quieres que tenga permisos para borrar repos solo porque necesita leer código.
El matiz de los agentes IA
Esto hace que 2026 sea diferente de 2023: las CLI ya no son solo para humanos tecleando. Agentes codificadores IA como Claude Code, Codex y el modo agente de Cursor llaman a CLIs de forma programática. Esto suma nuevos retos de autenticación:
Permisos delegados. Cuando Claude Code ejecuta gh pr create por ti, usa tus credenciales de GitHub. ¿Debe un agente IA tener tus mismos permisos? El mínimo privilegio dice que no, pero casi ninguna herramienta permite reducir el alcance solo para agentes.
Exposición de credenciales. Si tu API key está en una var de entorno, cualquier proceso puede leerla, incluido el subproceso del agente de IA. Herramientas como Claude Code han implementado scripts apiKeyHelper que generan tokens temporales bajo demanda, pero esto no es universal.
Auth sin cabeza para agentes. Un agente IA en entorno aislado no puede abrir un navegador. Device code flow funciona (el humano aprueba en otro dispositivo), pero las API keys son aún más comunes porque no requieren interacción humana.
Auditorías. Cuando un agente IA hace llamadas API con tus credenciales, el log de auditoría dice que tú hiciste esas llamadas. No hay manera estándar de distinguir "humano" de "agente actuando por humano".
Esto evoluciona rápido. Lo mejor que puedes hacer ahora:
- Usa tokens acotados al mínimo necesario para agentes
- Prefiere credenciales de vida corta (temporales, no API keys fijas)
- Usa credenciales dedicadas para agentes, distintas a tus credenciales personales
- Monitorea el uso de las APIs para detectar patrones inesperados
Marco de decisión
¿Eligiendo método de autenticación? Resumen rápido:
"Mis usuarios son desarrolladores en local" → OAuth con PKCE en navegador (mejor seguridad + UX suave)
"Mi CLI debe funcionar por SSH y en contenedores" → Device code flow como fallback, OAuth en navegador como primaria
"Esto corre en CI/CD sin humanos" → Client credentials o API keys acotadas
"Necesito implementar lo más rápido posible" → API keys (agrega rotación después)
"Clientes enterprise requieren SSO y MFA" → Cualquier flujo OAuth (device code o navegador), compatible con el stack enterprise
"Agentes IA usarán la CLI" → Soporta API keys (para integración fácil de agentes) + OAuth en navegador (para usuarios humanos), con permisos acotados y tokens de vida corta
FAQ
¿El device code flow es seguro?
Es seguro ante la mayoría de ataques, pero tiene una vulnerabilidad de phishing. Un atacante puede generar un código y engañar a usuarios para autorizarlo. Por eso AWS usa PKCE como predeterminado en SSO. Para entornos sin cabeza donde PKCE no es práctico, device code flow sigue siendo la mejor opción. Solo ten en cuenta el riesgo de phishing.
¿Debo guardar tokens en variables de entorno?
En CI/CD: sí, porque la plataforma los cifra en reposo e inyecta según ejecución. Para desarrollo local: no. Usa el llavero del SO. Las var de entorno se ven en listas de procesos y pueden ser logueadas o filtradas a procesos hijos.
¿Diferencia entre API key y personal access token?
En la práctica, poca. Ambos son credenciales de larga duración que autentican peticiones. Es más una diferencia organizacional: las API keys suelen estar ligadas a un proyecto/app, los PATs a cuentas de usuario. Algunos servicios los usan indistintamente.
¿Cada cuánto debo rotar credenciales?
Access tokens: cada hora o menos (refrescado automático). Refresh tokens: rota en cada uso (el servidor auth lo hace). API keys: al menos cada 90 días o inmediatamente si sospechas exposición. En la práctica, la mayoría solo rota API keys tras un incidente, que es tarde.
¿Cómo manejo auth en contenedores Docker?
Tres opciones, en orden de preferencia:
- Device code flow para uso interactivo (sirve porque el navegador está en otra máquina)
- Variables de entorno en tiempo de ejecución (
docker run -e API_KEY=${API_KEY}) para CI/CD - Credenciales montadas por volumen (
docker run -v ~/.config/tool:/root/.config/tool:ro) para desarrollo local
Nunca metas credenciales en la imagen. Nunca.
¿Y la autenticación MCP (Model Context Protocol)?
MCP es el nuevo estándar para que agentes IA se conecten a servicios externos. Introduce otra dimensión: el agente necesita credenciales para el servidor MCP, que a su vez necesita para las APIs downstream. Se está estandarizando aún. Por ahora, la mayoría de implementaciones usan API keys o tokens OAuth pasados en la config de MCP. Espera que esto evolucione rápido.
La autenticación en CLI cambia rápidísimo. Lo que era best-practice hace dos años (device code flow como default, archivos de credenciales en plano) ya está quedando atrás. Si sumas auth a una CLI hoy, empieza con OAuth en navegador + PKCE para humanos, API keys para automatización, y prepárate para el día en que los agentes de IA sean tus principales usuarios.

