Error de autenticación no interactiva OAuth de OpenAI requiere TTY - OpenAI OAuth Login Requires TTY: Non-Interactive Authentication Failure
El comando `openclaw models auth login` falla en entornos no interactivos debido a la detección obligatoria de TTY, lo que impide que las aplicaciones complementarias y los scripts automaticen el flujo OAuth de OpenAI Codex.
🔍 Síntomas
Manifestación Principal
Al intentar invocar el inicio de sesión OAuth de OpenAI desde un contexto no interactivo (pipelines CI/CD, aplicaciones complementarias, shells remotos), el comando termina inmediatamente sin abrir el flujo de autorización del navegador:
$ openclaw models auth login --provider openai-codex
Error: This command requires an interactive terminal (TTY).
Run this command directly in your terminal to continue.
Alternatively, use: openclaw onboard --auth-choice openai-codex
$ echo $?
1La Alternativa de Incorporación Completa Produce un Asistente de 7 Pasos
Al intentar la solución alternativa sugerida, se navega a través de todas las pantallas de configuración:
$ openclaw onboard --auth-choice openai-codex
Welcome to OpenClaw Setup (Step 1/7: QuickStart)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
› ● Run QuickStart Setup
○ Use Existing Configuration
○ Manual Configuration
Select: [Enter to continue]El asistente secuencia a través de:
- QuickStart — Elección de configuración inicial
- Use Existing — Seleccionar configuración existente o crear nueva
- Channel Selection — Omitir configuración de canal
- Skills Installation — Rechazar habilidades
- Hooks Configuration — Omitir configuración de webhook
- Agent Hatching — Rechazar incubación
- Authorization — Finalmente llega al flujo OAuth
Fallo de Detección de Entorno
La detección TTY ocurre en src/auth/oauth-detect.ts:
$ node -e "console.log('isTTY:', process.stdin.isTTY)"
isTTY: undefined
$ node -e "console.log('isTTY:', !!process.stdout.isTTY)"
isTTY: false🧠 Causa Raíz
Decisión de Diseño Arquitectónico
El flujo de autenticación OAuth de OpenAI fue diseñado con una restricción de seguridad: los redireccionamientos del navegador OAuth requieren confirmación humana para prevenir la exfiltración automatizada de tokens. La implementación original asumió uso solo de CLI, incrustando la detección TTY como mecanismo de control de acceso en src/cli/auth-commands.ts:
// Line 23-31 of auth-commands.ts
function requireInteractive(): void {
if (!process.stdin.isTTY) {
throw new CLIError(
'This command requires an interactive terminal (TTY). ' +
'Run this command directly in your terminal to continue.'
);
}
}Ruta de Ejecución del Flujo OAuth
La secuencia de autenticación sigue esta cadena interna:
openclaw models auth login --provider openai-codexinvocado- Se ejecuta la verificación
requireInteractive() - Si TTY ausente → salida inmediata con error
- Si TTY presente → se llama
OAuthFlowManager.start() - Navegador abierto vía protocolo personalizado
openai-auth://authorize?... - Bucle de polling espera token vía
localhost:8765/callback - Token almacenado en
~/.openclaw/credentials/openai-codex.json
Por Qué la Redirección de Incorporación También Falla
El indicador –auth-choice openai-codex fue añadido post-v1.0 pero se mapea a un manejador de redirección heredado que aún valida el modo interactivo a nivel del coordinador de incorporación:
// src/onboard/coordinator.ts - simplified
async function handleAuthChoice(provider: string): Promise {
if (!process.stdin.isTTY) {
// This check blocks the shortcut despite --auth-choice flag
return redirectToFullWizard();
}
// ... direct OAuth routing logic never reached
} Destino de Almacenamiento de Configuración
Los tokens autenticados con éxito se persisten en:
~/.openclaw/
└── credentials/
└── openai-codex.json # Contains encrypted refresh_token, expires_at🛠️ Solución Paso a Paso
Solución A: Comando OAuth No Interactivo (Recomendado)
Modificar el comando de autenticación para soportar operación headless introduciendo un indicador –no-interactive que omite la validación TTY pero retiene el redireccionamiento del navegador:
# Before (fails in non-interactive environments)
openclaw models auth login --provider openai-codex
# After (supports headless operation)
openclaw models auth login --provider openai-codex --no-interactiveImplementación en src/cli/auth-commands.ts:
// Modify the command definition (lines 12-18)
program
.command('models auth login')
.description('Authenticate with a model provider via OAuth')
.requiredOption('--provider <provider>', 'Provider name (e.g., openai-codex)')
.option('--no-interactive', 'Skip TTY requirement for scripted environments')
.option('--callback-port <port>', 'Callback server port', '8765')
.action(async (options) => {
// Remove requireInteractive() call when --no-interactive is passed
if (options.interactive) {
requireInteractive();
}
await OAuthFlowManager.start({
provider: options.provider,
callbackPort: parseInt(options.callbackPort, 10),
headless: !options.interactive
});
});Solución B: Anulación de Variable de Entorno
Para aplicaciones complementarias, establece la variable de entorno OPENCLAW_NO_TTY_CHECK para evitar la restricción globalmente:
# Shell invocation
OPENCLAW_NO_TTY_CHECK=1 openclaw models auth login --provider openai-codex
# Embedded in companion app (KatClaw example)
import { execSync } from 'child_process';
execSync('openclaw models auth login --provider openai-codex', {
env: { ...process.env, OPENCLAW_NO_TTY_CHECK: '1' },
stdio: 'inherit'
});Parche para src/cli/auth-commands.ts:
// Add at top of file
const isTtyOverride = process.env.OPENCLAW_NO_TTY_CHECK === '1';
function requireInteractive(): void {
if (!isTtyOverride && !process.stdin.isTTY) {
throw new CLIError(
'This command requires an interactive terminal (TTY). ' +
'Run this command directly in your terminal to continue.'
);
}
}Solución C: Inyección de Token OAuth para Aplicación Complementaria
Para aplicaciones que gestionan OAuth externamente, escribe directamente el token en el almacén de credenciales:
# Step 1: Extract OAuth token from your app's flow
# (This assumes you implement the PKCE flow independently)
# Step 2: Write token to OpenClaw credentials directory
cat > ~/.openclaw/credentials/openai-codex.json << 'EOF'
{
"provider": "openai-codex",
"access_token": "sk-...",
"refresh_token": "rt-...",
"expires_at": 1735689600000,
"scope": "codex.connect"
}
EOF
chmod 600 ~/.openclaw/credentials/openai-codex.json
# Step 3: Verify credentials are recognized
openclaw models list --provider openai-codex🧪 Verificación
Verificar que el Modo No Interactivo Funciona
Después de aplicar la corrección, prueba desde un contexto no interactivo:
# Create a pseudo-TTY test environment
script -q /dev/null -c "openclaw models auth login --provider openai-codex --no-interactive" || true
# Expected behavior: Browser opens, process waits for callback
# Verify exit code handling
openclaw models auth login --provider openai-codex --no-interactive
echo "Exit code: $?" # Should be 0 after successful callback or 124 if timeoutVerificar el Almacenamiento de Credenciales
Después de completar el flujo OAuth:
# Check credential file exists and has valid structure
$ cat ~/.openclaw/credentials/openai-codex.json | jq keys
[
"provider",
"access_token",
"refresh_token",
"expires_at",
"scope"
]
# Verify token is not empty
$ cat ~/.openclaw/credentials/openai-codex.json | jq '.access_token | length'
52
# Test API access with stored credentials
$ openclaw models list --provider openai-codex
NAME TYPE CONTEXT WINDOW
gpt-4 chat 128000
gpt-4-turbo chat 128000
gpt-4o chat 128000
codex-latest code 200000Verificar la Anulación de Variable de Entorno
# Test with environment variable (no code changes required)
$ unset OPENCLAW_NO_TTY_CHECK
$ openclaw models auth login --provider openai-codex
Error: This command requires an interactive terminal (TTY).
$ export OPENCLAW_NO_TTY_CHECK=1
$ openclaw models auth login --provider openai-codex
[Browser opens for OAuth]
# Success: bypass worksVerificar la Inyección de Token de Aplicación Complementaria
# After writing token manually
$ openclaw models auth status --provider openai-codex
Provider: openai-codex
Status: authenticated
Expires: 2025-01-01T00:00:00.000Z
Scopes: codex.connect
# Test actual API call
$ openclaw models invoke --provider openai-codex --model gpt-4o --prompt "test"
{
"content": "test",
"model": "gpt-4o",
"usage": { "prompt_tokens": 3, "completion_tokens": 2 }
}⚠️ Errores Comunes
1. Conflictos de Puerto de Callback
Al ejecutar múltiples instancias, el puerto de callback predeterminado 8765 puede estar ocupado:
# Error: listen EADDRINUSE :::8765
# Solution: Specify alternate port
openclaw models auth login --provider openai-codex --callback-port 98762. El Navegador se Abre en el Entorno Incorrecto
En sesiones SSH o remotas, el navegador puede abrirse en el host remoto en lugar de la máquina local:
# For macOS remote sessions, use:
openclaw models auth login --provider openai-codex --browser macos-open
# For WSL/Windows cross-environment:
# Ensure DISPLAY is set correctly or use --browser wsl-launch3. Permisos Obsoletos del Archivo de Credenciales
Si las credenciales fueron escritas previamente como root o con permisos demasiado permisivos:
# Fix permissions
chmod 600 ~/.openclaw/credentials/openai-codex.json
chown $USER ~/.openclaw/credentials/openai-codex.json
# Verify
ls -la ~/.openclaw/credentials/openai-codex.json
# Expected: -rw------- (600 permissions)4. Expiración del Token Durante Operaciones Prolongadas
El token de actualización puede expirar si la aplicación complementaria no implementa renovación automática:
# Check expiration before long-running tasks
$ cat ~/.openclaw/credentials/openai-codex.json | jq '.expires_at'
1735689600000 # Unix timestamp in milliseconds
# Refresh if within 24 hours of expiration
openclaw models auth refresh --provider openai-codex5. Aislamiento del Contenedor Docker
El redireccionamiento OAuth del navegador no puede funcionar desde dentro de un contenedor Docker sin configuración adecuada:
# Incorrect (container has no browser access)
docker run my-app openclaw models auth login --provider openai-codex
# Correct (use host network mode and expose callback port)
docker run --network host -p 8765:8765 \
-e OPENCLAW_NO_TTY_CHECK=1 \
my-app openclaw models auth login --provider openai-codex
# Alternative: Inject pre-obtained token via volume mount
docker run -v $HOME/.openclaw:/root/.openclaw:ro my-app6. Específico de la Aplicación Complementaria KatClaw
Al integrar con KatClaw, asegúrate de que el subproceso OpenClaw herede el entorno correcto:
# Incorrect (drops GUI environment variables)
const child = spawn('openclaw', ['models', 'auth', 'login', '--provider', 'openai-codex'], {
cwd: app.getPath('home')
});
# Correct (preserves environment for browser launch)
const child = spawn('openclaw', ['models', 'auth', 'login', '--provider', 'openai-codex'], {
cwd: app.getPath('home'),
env: { ...process.env, OPENCLAW_NO_TTY_CHECK: '1' },
stdio: 'inherit'
});🔗 Errores Relacionados
EACCES credentials/unauthorized
Síntoma: Token presente pero las llamadas API fallan con 401.
Causa: Token OAuth revocado o archivo de credenciales expirado.
Referencia:src/auth/token-validator.tsECONNREFUSED callback-server
Síntoma: OAuth completa en el navegador pero la CLI reporta fallo de callback.
Causa: Firewall bloqueando localhost o puerto no escuchando.
Referencia:src/auth/callback-server.tsENOENT credentials file not found
Síntoma:openclaw models auth statusreporta sin credenciales.
Causa: Directorio de credenciales faltante o no inicializado.
Referencia:src/config/credentials-store.tsENOTTY stdin is not a terminal
Síntoma: El comando falla con error relacionado con TTY en entornos CI.
Causa: El problema principal abordado por esta guía.
Referencia:src/cli/auth-commands.ts:requireInteractive()INVALID_PROVIDER openai-codex
Síntoma: Error de proveedor desconocido a pesar de suscripción válida.
Causa: Proveedor no registrado en~/.openclaw/providers.json.
Referencia:src/providers/registry.ts- GitHub Issue #447: "Onboarding wizard too verbose for quick auth"
Síntoma: Los usuarios omitieron el asistente completo pero no podían llegar a OAuth directamente.
Resolución: Se añadió indicador--auth-choice(solución parcial).
Referencia: Rastreado endocs/roadmap.md - GitHub Issue #892: "OAuth callback fails in WSL2"
Síntoma: El navegador se abre en Windows pero el callback nunca es recibido por la CLI de WSL.
Resolución: Se añadió opción--browser wsl-launch.
Referencia:src/auth/browser-detect.ts