# Fluxo de Autenticacao OAuth - TecJustica MCP v4

Documentacao do fluxo de autenticacao OAuth 2.1 entre Claude, MCP Server e Supabase.

---

## Visao Geral

O TecJustica MCP v4 usa **SupabaseProvider** (FastMCP) com **Dynamic Client Registration (DCR)** e **DualTokenVerifier** para autenticacao dual (JWT Supabase + API Keys).

```
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  Claude.ai  │     │ MCP Server  │     │  Supabase   │
│  (Cliente)  │     │  (Railway)  │     │ OAuth Server│
└──────┬──────┘     └──────┬──────┘     └──────┬──────┘
       │                   │                   │
       │ 1. Discovery      │                   │
       │──────────────────>│                   │
       │                   │                   │
       │ 2. DCR (register) │                   │
       │──────────────────>│ (delega ao Supa)  │
       │                   │──────────────────>│
       │                   │                   │
       │ 3. Authorize      │                   │
       │──────────────────>│ (redireciona)     │
       │                   │──────────────────>│
       │                   │                   │
       │ 4. Login + Consent│                   │
       │───────────────────────────────────────>│
       │                   │                   │
       │ 5. Auth callback  │                   │
       │──────────────────>│ token exchange    │
       │                   │──────────────────>│
       │                   │                   │
       │ 6. JWT (ES256)    │                   │
       │<──────────────────│                   │
       │                   │                   │
       │ 7. Usa tools      │                   │
       │──────────────────>│ valida via JWKS   │
       │                   │                   │
```

---

## Componentes

### 1. SupabaseProvider (FastMCP)

O `SupabaseProvider` do FastMCP gerencia todo o fluxo OAuth automaticamente:
- **DCR**: Clientes MCP (como Claude) se registram dinamicamente
- **Authorize/Token**: Delega ao Supabase OAuth Server
- **Consent**: Gerenciado pelo Supabase (nao precisa de frontend proprio)

```python
auth = SupabaseProvider(
    project_url=supabase_url,      # URL do projeto Supabase
    base_url=base_url,             # URL publica do MCP (https://mcp.tecjustica.com)
    token_verifier=dual_verifier,  # DualTokenVerifier
)
```

**Nao precisa de**: `client_id`, `client_secret`, `JWT_SIGNING_KEY`, `config_url`.

### 2. DualTokenVerifier

Valida dois tipos de token:

| Tipo | Formato | Validacao |
|------|---------|-----------|
| **API Key** | `tk_...` (64 chars hex) | SHA-256 hash vs env var `API_KEY_HASHES` |
| **JWT Supabase** | `eyJ...` (Bearer) | JWKS endpoint (ES256) |

```python
class DualTokenVerifier(TokenVerifier):
    async def verify_token(self, token: str) -> AccessToken | None:
        if token.startswith("tk_"):
            # Hash SHA-256 e compara com API_KEY_HASHES
            token_hash = hashlib.sha256(token.encode()).hexdigest()
            key_data = self.api_keys.get(token_hash)
            if key_data:
                return AccessToken(claims={"sub": key_data["user_id"], ...})
            return None
        # Delega JWTs ao JWTVerifier
        return await self.jwt_verifier.verify_token(token)
```

### 3. JWTVerifier (JWKS + ES256)

Valida JWTs do Supabase usando JWKS (chaves publicas):

```python
jwt_verifier = JWTVerifier(
    jwks_uri=f"{supabase_url}/auth/v1/.well-known/jwks.json",
    issuer=f"{supabase_url}/auth/v1",
    algorithm="ES256",  # Supabase agora usa ES256 (assimetrico)
)
```

**Importante**: O Supabase migrou de HS256 (simetrico) para **ES256** (assimetrico). Isso significa:
- Nao precisa de `SUPABASE_JWT_SECRET` no servidor
- Validacao via JWKS (chaves publicas rotacionaveis)
- Mais seguro (servidor nunca tem acesso a chave privada)

### 4. Supabase OAuth Server

- Provedor de identidade (IdP)
- Autentica usuarios (email/senha, Google, GitHub, etc.)
- Emite JWTs assinados com ES256
- Gerencia consent automaticamente

---

## Fluxo Detalhado

### Fase 1: Discovery + DCR (automatico)

**1. Claude faz discovery do servidor OAuth**
```http
GET /.well-known/oauth-authorization-server HTTP/1.1
Host: mcp.tecjustica.com

Response:
{
  "issuer": "https://mcp.tecjustica.com/",
  "authorization_endpoint": "https://mcp.tecjustica.com/authorize",
  "token_endpoint": "https://mcp.tecjustica.com/token",
  "registration_endpoint": "https://mcp.tecjustica.com/register",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "code_challenge_methods_supported": ["S256"]
}
```

**2. Claude registra-se como cliente (DCR)**

O `SupabaseProvider` delega o registro ao Supabase OAuth Server automaticamente.

```http
POST /register HTTP/1.1
Host: mcp.tecjustica.com
Content-Type: application/json

{
  "redirect_uris": ["https://claude.ai/api/mcp/auth_callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"]
}
```

### Fase 2: Autorizacao

**3. Claude redireciona usuario para login**

O `SupabaseProvider` redireciona para o Supabase Auth.

**4. Usuario faz login no Supabase**
- Tela de login do Supabase Auth
- Email/senha ou OAuth social (Google, GitHub, etc.)
- Consent automatico (sem pagina separada)

### Fase 3: Token Exchange

**5. Supabase retorna auth code, MCP troca por JWT**

O `SupabaseProvider` faz o token exchange automaticamente.

**6. Claude recebe JWT do Supabase (ES256)**

```python
# JWT decodificado
{
  "aud": "authenticated",
  "exp": 1766876536,
  "iat": 1735340536,
  "iss": "https://pglghyznirxkewcmuhvp.supabase.co/auth/v1",
  "sub": "76ba8190-b43d-4665-84cd-0c30f3bc7b8e",  # user_id
  "email": "usuario@email.com",
  "role": "authenticated"
}
```

### Fase 4: Uso do MCP

**7. Claude usa tools com Bearer token**
```http
POST /mcp HTTP/1.1
Host: mcp.tecjustica.com
Authorization: Bearer eyJhbGciOiJFUzI1NiIs...
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "listar_processos",
    "arguments": {}
  }
}
```

O `DualTokenVerifier` valida o token via JWKS e extrai o `user_id` para RLS.

---

## Auth via API Key (alternativa)

Para clientes programaticos que nao suportam OAuth (scripts, CLIs):

```bash
# API Key funciona como Bearer token direto
curl -X POST https://mcp.tecjustica.com/mcp \
  -H "Authorization: Bearer tk_0bd3..." \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize",...}'
```

**Formato da env var `API_KEY_HASHES`:**
```
sha256hash:user_id:email[,sha256hash2:user_id2:email2]
```

O `DualTokenVerifier` detecta o prefixo `tk_`, calcula SHA-256 e compara com os hashes configurados.

---

## Variaveis de Ambiente

| Variavel | Obrigatoria | Descricao |
|----------|-------------|-----------|
| `SUPABASE_URL` | Sim | URL do projeto Supabase |
| `SUPABASE_SERVICE_KEY` | Sim | Service key para operacoes admin |
| `AUTH_ENABLED` | Nao | `true` (default) ou `false` |
| `MCP_BASE_URL` | Sim | URL publica do MCP (`https://mcp.tecjustica.com`) |
| `API_KEY_HASHES` | Nao | Hashes de API keys (formato `hash:uid:email`) |
| `OPENROUTER_API_KEY` | Sim | Key para OpenRouter (LLM) |

**Nao precisa mais de**: `JWT_SIGNING_KEY`, `SUPABASE_JWT_SECRET`, `SUPABASE_OAUTH_CLIENT_ID`, `SUPABASE_OAUTH_CLIENT_SECRET`.

---

## Erros Comuns

### 401 "invalid_token" no /mcp

**Causas possiveis:**
1. Token nao e do Supabase (ex: PJE/Keycloak) — usar endpoint Supabase
2. Token expirado — reconectar no Claude.ai
3. API Key invalida — verificar hash em `API_KEY_HASHES`

### OAuth funciona mas /mcp falha

**Solucao:**
1. Remover connector no Claude.ai
2. Adicionar novamente
3. Fazer login novamente

### Missing session ID

**Causa:** Chamou tool sem enviar header `mcp-session-id`

**Solucao:** Capturar session ID do `initialize` e enviar em todas as requests.

---

## Diferenca do sistema anterior (v3)

| Aspecto | v3 (OIDCProxy) | v4 (SupabaseProvider) |
|---------|----------------|----------------------|
| Provider | `OIDCProxy` | `SupabaseProvider` |
| Algoritmo JWT | HS256 (simetrico) | ES256 (assimetrico) |
| Validacao | `SUPABASE_JWT_SECRET` direto | JWKS (chaves publicas) |
| Client credentials | `client_id` + `client_secret` | DCR automatico |
| Signing key | `JWT_SIGNING_KEY` proprio | Nao precisa |
| Consent page | Frontend separado (Vercel) | Gerenciado pelo Supabase |
| Env vars necessarias | 6+ | 3 (SUPABASE_URL, MCP_BASE_URL, SUPABASE_SERVICE_KEY) |

---

## Referencias

- [FastMCP SupabaseProvider Docs](https://gofastmcp.com/servers/auth/supabase)
- [Supabase OAuth Server](https://supabase.com/docs/guides/auth/oauth-server)
- [OAuth 2.1 Spec](https://oauth.net/2.1/)
