> ## Documentation Index
> Fetch the complete documentation index at: https://chatcli.edilsonfreitas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Autenticação OAuth

> Autentique-se com provedores de IA via OAuth, sem precisar gerenciar chaves de API manualmente.

O ChatCLI suporta autenticação via **OAuth 2.0 com PKCE** e **Device Flow (RFC 8628)** para provedores que oferecem essas opções. Isso permite que você use seu plano existente (como **ChatGPT Plus**, **Codex**, **Claude Pro** ou **GitHub Copilot**) diretamente no terminal, sem precisar gerar ou colar chaves de API.

***

## Métodos de Autenticação

| Método                       | Descrição                                             | Quando Usar                                               |
| ---------------------------- | ----------------------------------------------------- | --------------------------------------------------------- |
| **Chave de API**             | Variável de ambiente no `.env` (ex: `OPENAI_API_KEY`) | Acesso programático, CI/CD, API Keys da plataforma        |
| **OAuth (login interativo)** | Comando `/auth login` no terminal                     | Planos ChatGPT Plus/Codex, Claude Pro, sem gerenciar keys |

<Info>Os dois métodos podem coexistir. O ChatCLI prioriza credenciais OAuth quando ambas estão disponíveis.</Info>

<Note>
  **Suporte OAuth por provedor:**

  * **Com suporte a OAuth:** OpenAI (ChatGPT Plus/Codex), Anthropic (Claude Pro) e GitHub Copilot (Device Flow).
  * **Apenas chave de API:** GoogleAI, xAI, ZAI, MiniMax, Moonshot (Kimi), StackSpot e Ollama. Para esses provedores, configure a chave via variável de ambiente no `.env` ou use `/auth set`.
</Note>

***

## Comandos `/auth`

Todos os comandos de autenticação possuem **auto-completação** — basta digitar `/auth` e pressionar `Tab`.

### Ver Status

```bash theme={"system"}
/auth status
```

Exibe o status de autenticação de todos os provedores configurados, incluindo tipo de credencial (API Key vs OAuth), validade do token e origem.

### Login via OAuth

```bash theme={"system"}
/auth login openai-codex
/auth login anthropic
/auth login github-copilot
/auth login github-models
```

<Steps>
  <Step title="Navegador abre automaticamente">
    O navegador abre na página de login do provedor.
  </Step>

  <Step title="Autorize o acesso">
    **OpenAI:** um servidor HTTP local captura o callback automaticamente (porta **1455**).

    **Anthropic:** um servidor HTTP local em `localhost:<porta-aleatória>/callback` captura o código automaticamente. Após autorizar, o navegador é redirecionado para a página de sucesso oficial do Anthropic e o terminal completa o login. Se o servidor local não puder iniciar (porta indisponível, firewall) ou se `CHATCLI_ANTHROPIC_LEGACY_OAUTH=1` estiver definido, o ChatCLI cai automaticamente no fluxo legado de **copiar e colar** o código.

    **GitHub Copilot:** insira o código do dispositivo exibido no terminal na página do GitHub.
  </Step>

  <Step title="Provedor disponível imediatamente">
    O provedor aparece imediatamente no `/switch` — **sem reiniciar o app**.
  </Step>
</Steps>

#### Provedores Suportados

| Provedor       | Comando                      | Planos Compatíveis                                                   |
| -------------- | ---------------------------- | -------------------------------------------------------------------- |
| OpenAI         | `/auth login openai-codex`   | ChatGPT Plus, Codex, Team, Enterprise                                |
| Anthropic      | `/auth login anthropic`      | Claude Pro, Team                                                     |
| GitHub Copilot | `/auth login github-copilot` | Copilot Individual, Business, Enterprise                             |
| GitHub Models  | `/auth login github-models`  | Qualquer conta GitHub (PAT) — [detalhes](/pt/features/github-models) |

### Logout

```bash theme={"system"}
/auth logout openai-codex
/auth logout anthropic
/auth logout github-copilot
```

Remove as credenciais OAuth armazenadas para o provedor específicado.

***

## Detalhes Técnicos dos Fluxos OAuth

Esta seção descreve como cada fluxo OAuth funciona internamente, incluindo URLs, parâmetros e comportamento do ChatCLI.

### Anthropic OAuth (PKCE + Callback Localhost, com fallback para paste)

O fluxo da Anthropic usa OAuth 2.0 com PKCE (Proof Key for Code Exchange) e um servidor HTTP local em `localhost:<porta-aleatória>/callback` para capturar o código de autorização — o mesmo padrão usado pelo Claude Code CLI. O fluxo legado de **copiar e colar** o código permanece disponível como fallback automático.

#### Fluxo primário (callback local)

<Steps>
  <Step title="Geração do PKCE e início do servidor local">
    O ChatCLI gera um `code_verifier` aleatório, calcula o `code_challenge` usando SHA-256 (método `S256`), e sobe um servidor HTTP em uma porta aleatória de `localhost`. Um `state` de 32 bytes (base64url, 43 caracteres) é gerado para proteção CSRF.
  </Step>

  <Step title="Abertura do navegador">
    O navegador abre na URL de autorização da Anthropic com `code=true`, o PKCE challenge, o `state` e o `redirect_uri` apontando para o servidor local.
  </Step>

  <Step title="Usuário autoriza no navegador">
    O usuário faz login no Claude e autoriza o acesso. O navegador é redirecionado para `http://localhost:<porta>/callback?code=...&state=...`.
  </Step>

  <Step title="Validação CSRF e troca de tokens">
    O servidor local valida o `state` recebido contra o gerado, troca o código por tokens via `platform.claude.com/v1/oauth/token` e encerra o servidor. O navegador é redirecionado para a página de sucesso oficial do Anthropic (`platform.claude.com/oauth/code/success`).
  </Step>
</Steps>

#### Fluxo de fallback (copiar e colar)

Acionado automaticamente quando o servidor local não consegue se vincular à porta (firewall, porta em uso) ou quando `CHATCLI_ANTHROPIC_LEGACY_OAUTH=1` é definido explicitamente.

<Steps>
  <Step title="Abertura do navegador no fluxo legado">
    O ChatCLI abre a URL de autorização legada (`console.anthropic.com` como `redirect_uri`).
  </Step>

  <Step title="Usuário copia o código">
    Após autorizar, a página do console exibe um código no formato `código#state`. O usuário cola o texto completo no terminal — o ChatCLI separa código e `state` automaticamente.
  </Step>

  <Step title="Troca do código por tokens">
    O ChatCLI envia código, `state` e `code_verifier` para o endpoint de tokens e recebe access\_token + refresh\_token.
  </Step>
</Steps>

| Parâmetro               | Valor                                                                                                        |
| ----------------------- | ------------------------------------------------------------------------------------------------------------ |
| Auth URL (primário)     | `https://claude.com/cai/oauth/authorize`                                                                     |
| Auth URL (fallback)     | `https://claude.ai/oauth/authorize`                                                                          |
| Token URL (primário)    | `https://platform.claude.com/v1/oauth/token`                                                                 |
| Token URL (fallback)    | `https://console.anthropic.com/v1/oauth/token`                                                               |
| Redirect URI (primário) | `http://localhost:<porta-aleatória>/callback`                                                                |
| Redirect URI (fallback) | `https://console.anthropic.com/oauth/code/callback`                                                          |
| Página de sucesso       | `https://platform.claude.com/oauth/code/success?app=claude-code`                                             |
| Client ID               | `9d1c250a-e61b-44d9-88ed-5944d1962f5e`                                                                       |
| Scopes                  | `org:create_api_key user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload` |
| PKCE Method             | `S256` (SHA-256 code challenge)                                                                              |
| Tamanho do `state`      | 32 bytes (base64url, 43 caracteres)                                                                          |

<Warning>
  **Validações silenciosas do `claude.ai`** — o fluxo primário **só funciona** se três parâmetros estiverem corretos. Caso contrário, a página de autorização retorna apenas "Invalid request format" sem código de erro:

  * `code=true` deve estar presente na query string
  * `state` deve ter exatamente 32 bytes (43 caracteres base64url) — `state` de 16 bytes é silenciosamente rejeitado
  * A URL de autorização deve ser `claude.com/cai/oauth/authorize` (faz 307 para `claude.ai/oauth/authorize`, e o redirect define cookies que a SPA precisa)
</Warning>

<Warning>
  A troca e o refresh de tokens usam um `http.Client` puro (sem transporte customizado) com header `User-Agent: claude-cli/2.1.2 (external, cli)` para evitar fingerprinting TLS pelo Cloudflare. Usar um HTTP client com `LoggingTransport` causa rejeição pela CDN da Anthropic.
</Warning>

O refresh tenta primeiro `platform.claude.com` e cai automaticamente para `console.anthropic.com/v1/oauth/token` se o token tiver sido emitido pelo fluxo legado de paste.

***

### OpenAI Codex OAuth (PKCE + Callback Localhost)

O fluxo da OpenAI usa OAuth 2.0 com PKCE e um servidor HTTP local para capturar o callback automaticamente.

<Steps>
  <Step title="Servidor local inicia na porta 1455">
    O ChatCLI inicia um servidor HTTP em `http://localhost:1455` para receber o callback OAuth.
  </Step>

  <Step title="Navegador abre na página de autorização">
    O navegador abre na URL de autorização da OpenAI com o PKCE challenge e um parâmetro `state` para validação CSRF.
  </Step>

  <Step title="Usuário autoriza no navegador">
    Após login e autorização, o navegador redireciona para `http://localhost:1455/auth/callback` com o código de autorização.
  </Step>

  <Step title="Validação CSRF e troca de tokens">
    O servidor local válida o parâmetro `state` contra o valor gerado originalmente (proteção CSRF), troca o código por tokens e encerra o servidor.
  </Step>
</Steps>

| Parâmetro    | Valor                                                                          |
| ------------ | ------------------------------------------------------------------------------ |
| Auth URL     | `https://auth.openai.com/oauth/authorize`                                      |
| Token URL    | `https://auth.openai.com/oauth/token`                                          |
| Redirect URI | `http://localhost:1455/auth/callback`                                          |
| Client ID    | `app_EMoamEEZ73f0CkXaXp7hrann` (sobrescrevível via `CHATCLI_OPENAI_CLIENT_ID`) |
| Scopes       | `openid profile email offline_access`                                          |
| PKCE Method  | `S256`                                                                         |

<Tip>O refresh de tokens é automático e utiliza o HTTP client padrão com logging.</Tip>

***

### GitHub Copilot Device Flow (RFC 8628)

O GitHub Copilot usa o **Device Authorization Grant** (RFC 8628), um fluxo projetado para dispositivos sem navegador integrado, como terminais CLI.

<Steps>
  <Step title="Requisição do device code">
    O ChatCLI solicita um `device_code` e um `user_code` ao endpoint do GitHub.
  </Step>

  <Step title="Exibição do código no terminal">
    O ChatCLI exibe o `user_code` e a URL de verificação (`https://github.com/login/device`) para o usuário.
  </Step>

  <Step title="Usuário autoriza no navegador">
    O usuário acessa a URL, insere o `user_code` e autoriza o acesso do ChatCLI.
  </Step>

  <Step title="Polling até autorização">
    O ChatCLI faz polling no endpoint de tokens a cada 5 segundos até receber o access token ou um erro terminal.
  </Step>
</Steps>

| Parâmetro         | Valor                                                                   |
| ----------------- | ----------------------------------------------------------------------- |
| Device Code URL   | `https://github.com/login/device/code`                                  |
| Token Polling URL | `https://github.com/login/oauth/access_token`                           |
| Client ID         | `Ov23lifEydOk2Non90tJ` (sobrescrevível via `CHATCLI_COPILOT_CLIENT_ID`) |
| Scope             | `read:user`                                                             |
| Timeout máximo    | 15 minutos                                                              |

**Respostas do polling:**

| Resposta                | Ação                               |
| ----------------------- | ---------------------------------- |
| `authorization_pending` | Continua polling normalmente       |
| `slow_down`             | Aumenta o intervalo em +5 segundos |
| `expired_token`         | Falha — o device code expirou      |
| `access_denied`         | Falha — o usuário negou acesso     |

<Info>Tokens do GitHub Copilot são não-expirantes e não possuem refresh token. São persistentes até revogação manual na página de configurações do GitHub.</Info>

***

## Fluxo Completo: Do Zero ao Primeiro Prompt

Se você está começando **sem nenhuma credencial configurada**, siga estes passos:

<Steps>
  <Step title="Inicie o ChatCLI">
    Funciona mesmo sem credenciais configuradas.

    ```bash theme={"system"}
    chatcli
    ```
  </Step>

  <Step title="Faça login via OAuth">
    ```bash theme={"system"}
    /auth login openai-codex
    ```
  </Step>

  <Step title="Autorize no navegador">
    O navegador abre automaticamente na página de login do provedor.
  </Step>

  <Step title="Troque para o provedor">
    ```bash theme={"system"}
    /switch
    ```
  </Step>

  <Step title="Envie seu primeiro prompt">
    ```text theme={"system"}
    Olá, como você está?
    ```
  </Step>
</Steps>

***

## Roteamento Automático de Endpoints (OpenAI)

O ChatCLI detecta automaticamente o tipo de credencial e roteia as requisições para o endpoint correto:

| Credencial            | Endpoint                                  | API Format                         |
| --------------------- | ----------------------------------------- | ---------------------------------- |
| `OPENAI_API_KEY`      | `api.openai.com/v1/responses`             | Responses API (padrão)             |
| `OPENAI_API_KEY`      | `api.openai.com/v1/chat/completions`      | Chat Completions (modelos legados) |
| OAuth (`/auth login`) | `chatgpt.com/backend-api/codex/responses` | Responses API (streaming SSE)      |

<Tip>Você não precisa configurar nada — o roteamento é automático baseado no tipo de token.</Tip>

***

## Armazenamento de Credenciais

As credenciais OAuth são salvas com **criptografia AES-256-GCM** em:

```text theme={"system"}
~/.chatcli/auth-profiles.json
```

### Detalhes de Criptografia

| Aspecto               | Detalhe                                        |
| --------------------- | ---------------------------------------------- |
| Algoritmo             | AES-256-GCM (authenticated encryption)         |
| Arquivo da chave      | `~/.chatcli/.auth-key` (32 bytes aleatórios)   |
| Permissão da chave    | `0o600` (somente leitura/escrita pelo dono)    |
| Formato criptografado | `chatcli-enc:v1:` + Base64(nonce + ciphertext) |
| Geração da chave      | Automática na primeira utilização              |

A chave de criptografia é gerada automaticamente e armazenada em `~/.chatcli/.auth-key`. Dados não-criptografados de versões anteriores são detectados automaticamente (ausência do prefixo `chatcli-enc:v1:`) e migrados para o formato criptografado na próxima gravação.

Cada perfil armazenado contém:

* **Access token** (criptografado)
* **Refresh token** (criptografado, quando aplicável)
* **Expiry** (timestamp em milissegundos)
* **Account ID** e **email** do provedor
* **Tipo de provedor** (anthropic, openai-codex, github-copilot)

Para personalizar o diretório de armazenamento, defina a variável de ambiente:

```bash theme={"system"}
export CHATCLI_AUTH_DIR="~/.config/chatcli/auth"
```

***

## Validação de Tokens

O ChatCLI implementa validação rigorosa de tokens OAuth para prevenir uso de credenciais inválidas ou expiradas:

### Validação de Access Token

* **Rejeição de tokens vazios** — Tokens com access token vazio são rejeitados imediatamente, sem tentar fazer requests. Isso previne erros confusos de "unauthorized" quando as credenciais estão corrompidas.
* **Validação de expiração** — O campo `expiry` é verificado antes de cada request. Tokens expirados disparam o fluxo de refresh automaticamente.

### Tempo de Vida Máximo de Token (CHATCLI\_MAX\_TOKEN\_LIFETIME)

Para ambientes de produção com requisitos de conformidade, você pode limitar o tempo de vida máximo de tokens:

```bash theme={"system"}
# Limitar tokens a 24 horas (padrão: 720h / 30 dias)
export CHATCLI_MAX_TOKEN_LIFETIME=24h
```

<Info>
  Quando o tempo de vida máximo é atingido, o token é invalidado e o usuário precisa fazer login novamente via `/auth login`. Isso garante rotação periódica de credenciais mesmo quando o refresh token ainda é válido.
</Info>

| Variável                     | Descrição                                                                         | Padrão           |
| ---------------------------- | --------------------------------------------------------------------------------- | ---------------- |
| `CHATCLI_MAX_TOKEN_LIFETIME` | Tempo de vida máximo de tokens OAuth/JWT. Aceita durações Go (ex: `24h`, `168h`). | `720h` (30 dias) |

***

## Renovação Automática de Tokens

O ChatCLI renova tokens expirados automaticamente em duas camadas:

<CardGroup cols={2}>
  <Card title="Renovação Proativa" icon="clock">
    Ao resolver credenciais para um request, o ChatCLI verifica se o token está expirado (`IsExpired()`) ou prestes a expirar (`IsExpiringSoon()` com margem de **5 minutos**). Se sim, o refresh é executado **antes** do request.
  </Card>

  <Card title="Renovação Reativa" icon="rotate">
    Se um request retornar erro **HTTP 401**, o ChatCLI invalida o cache de credenciais, executa o refresh do token, recria o cliente HTTP e retenta o request automaticamente — tudo transparente para o usuário.
  </Card>
</CardGroup>

<Info>A margem de segurança de 5 minutos antes da expiração real evita race conditions em que o token expira entre a verificação e o envio do request.</Info>

Tokens do GitHub Copilot (Device Flow) **não expiram** e não possuem refresh token — são persistentes até revogação manual.

***

## Sincronização com CLIs Externos

O ChatCLI pode importar credenciais de CLIs externos via `SyncExternalCliCreds()`:

| CLI Externo          | Caminhos Verificados                                | Perfil Importado       |
| -------------------- | --------------------------------------------------- | ---------------------- |
| **Claude Code**      | `~/.claude/credentials.json` ou `~/.claude.json`    | `anthropic-oauth-sync` |
| **OpenAI Codex CLI** | `~/.codex/credentials.json` ou `~/.codex/auth.json` | `openai-codex-sync`    |

<Note>A importação só ocorre se as credenciais externas forem **mais recentes** que as já armazenadas. Isso garante que um login feito diretamente no ChatCLI não seja sobrescrito por dados antigos de outro CLI.</Note>

***

## Prioridade de Resolução de Credenciais

Ao determinar qual credencial usar para um provedor, o ChatCLI segue está ordem de prioridade:

<Steps>
  <Step title="Auth-profiles store (OAuth/Token)">
    Credenciais OAuth armazenadas em `auth-profiles.json`, incluindo perfis sincronizados de CLIs externos. O refresh automático é aplicado nesta camada.
  </Step>

  <Step title="Variáveis de ambiente">
    Variáveis como `ANTHROPIC_OAUTH_TOKEN`, `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` e `GITHUB_COPILOT_TOKEN`.
  </Step>
</Steps>

**Sistema de prefixos:** o valor das credenciais pode incluir prefixos que indicam o tipo ao provedor:

| Prefixo   | Significado                  |
| --------- | ---------------------------- |
| `oauth:`  | Token obtido via fluxo OAuth |
| `apikey:` | Chave de API tradicional     |
| `token:`  | Token genérico (ex: Copilot) |

***

### Configuração Avançada

| Variável                         | Descrição                                                                                                                                                                                                                                           |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CHATCLI_OPENAI_CLIENT_ID`       | Permite sobrescrever o client ID do OAuth da OpenAI                                                                                                                                                                                                 |
| `CHATCLI_COPILOT_CLIENT_ID`      | Permite sobrescrever o client ID do Device Flow do GitHub Copilot (padrão: `Ov23lifEydOk2Non90tJ`)                                                                                                                                                  |
| `COPILOT_API_BASE_URL`           | URL base da API do Copilot para ambientes enterprise (padrão: `https://api.githubcopilot.com`)                                                                                                                                                      |
| `CHATCLI_ANTHROPIC_LEGACY_OAUTH` | Quando definido como `1`, força o fluxo legado de **copiar e colar** o código no `/auth login anthropic`, ignorando o callback local. Útil em ambientes onde o `localhost` não é acessível (containers, SSH sem port-forward, firewall restritivo). |

***

## Solução de Problemas

<AccordionGroup>
  <Accordion title="Erro de autenticação ao clicar no link OAuth (OpenAI)">
    Verifique se a porta de callback não está em uso por outra aplicação. O servidor de callback da OpenAI precisa da porta **1455** para capturar o retorno.
  </Accordion>

  <Accordion title="Anthropic: callback local não funciona ou navegador trava em localhost">
    O fluxo primário usa um servidor HTTP local em `localhost:<porta-aleatória>/callback`. Se sua porta estiver bloqueada por firewall ou se você estiver em um ambiente sem `localhost` acessível (containers, sessões SSH sem port-forward), force o fluxo legado de paste:

    ```bash theme={"system"}
    export CHATCLI_ANTHROPIC_LEGACY_OAUTH=1
    /auth login anthropic
    ```

    No fluxo legado, o navegador abre na página do console que exibe o código no formato `código#state`. Copie **o texto completo** (incluindo a parte após o `#`) e cole no terminal — o ChatCLI separa código e state automaticamente.
  </Accordion>

  <Accordion title="Anthropic: página de autorização retorna &#x22;Invalid request format&#x22;">
    O `claude.ai` valida silenciosamente três parâmetros do fluxo primário e retorna apenas "Invalid request format" se algum estiver errado:

    * `code=true` ausente na query string
    * `state` com tamanho diferente de 32 bytes (43 caracteres base64url)
    * URL de autorização diferente de `claude.com/cai/oauth/authorize`

    Se você modificou o código da função `loginAnthropicLocalhost`, verifique esses três pontos antes de qualquer outra coisa.
  </Accordion>

  <Accordion title="Anthropic: erro 403 ou conexão recusada na troca de tokens">
    Isso geralmente ocorre quando um HTTP client customizado (com LoggingTransport) é usado. O ChatCLI usa um `http.Client` puro para a troca de tokens da Anthropic, evitando fingerprinting TLS pelo Cloudflare. Se você estiver desenvolvendo, certifique-se de que a função `exchangeAnthropicToken` usa um client sem transporte customizado.
  </Accordion>

  <Accordion title="Provedor não aparece no /switch após login">
    Execute `/auth status` para verificar se o token foi salvo corretamente. Se necessário, tente `/auth logout <provedor>` seguido de `/auth login <provedor>`.
  </Accordion>

  <Accordion title="GitHub Copilot: authorization denied by user">
    Certifique-se de que sua conta GitHub possui uma assinatura ativa do Copilot (Individual, Business ou Enterprise). Verifique em [https://github.com/settings/copilot](https://github.com/settings/copilot) se o Copilot está habilitado.
  </Accordion>

  <Accordion title="GitHub Copilot: device code expirado">
    O device code tem validade limitada. Se o polling exceder **15 minutos** sem autorização, o código expira. Execute `/auth login github-copilot` novamente para gerar um novo código.
  </Accordion>

  <Accordion title="Token expirado">
    Os tokens OAuth são renovados automaticamente de duas formas:

    * **Proativamente**: ao resolver credenciais, se o token estiver expirado ou dentro da margem de 5 minutos, o refresh é tentado antes do request.
    * **Reativamente**: se um request retornar erro 401, o ChatCLI invalida o cache de credenciais, tenta renovar o token OAuth, recria o cliente e retenta o request automaticamente.

    Se ambas as tentativas falharem (ex: refresh token também expirado), faça login novamente com `/auth login`.

    Tokens do GitHub Copilot (Device Flow) não expiram e não possuem refresh token — são persistentes até revogação manual.
  </Accordion>
</AccordionGroup>

***

## Próximos Passos

<CardGroup cols={2}>
  <Card title="Referência de Comandos" icon="rectangle-list" href="/pt/reference/command-reference">
    Lista completa de todos os comandos disponíveis.
  </Card>

  <Card title="Configuração (.env)" icon="gear" href="/pt/reference/configuration">
    Todas as variáveis de ambiente disponíveis.
  </Card>

  <Card title="Uso Básico" icon="graduation-cap" href="/pt/core-concepts/basic-usage">
    Aprenda os fundamentos do ChatCLI.
  </Card>
</CardGroup>

***
