# Interceptação de Callback OAuth Google Calendar ## Visão Geral Este documento explica como o dashboard intercepta o callback do Google OAuth antes de enviar para o n8n, permitindo salvar o status da integração no banco de dados. ## Fluxo Completo ``` 1. Usuário clica em "Conectar Google Calendar" no dashboard ↓ 2. Dashboard gera oauth_url do Google diretamente: - client_id = NEXT_PUBLIC_GOOGLE_CLIENT_ID - redirect_uri = http://localhost:3000/api/google-calendar/callback - state = user_id - scope = https://www.googleapis.com/auth/calendar - access_type = offline - prompt = consent ↓ 3. Dashboard redireciona usuário para oauth_url do Google ↓ 4. Usuário autoriza no Google ↓ 5. Google redireciona para: http://localhost:3000/api/google-calendar/callback?code=...&state=...&scope=... ↓ 6. Dashboard intercepta callback: - Salva status "connecting" na tabela portal.integrations (usando state = user_id) - Redireciona para: https://n8n.automatizase.com.br/rest/oauth2-credential/callback?code=...&state=...&scope=... ↓ 7. n8n processa callback normalmente: - Troca code por access_token e refresh_token - Salva na credencial OAuth2 - Redireciona de volta para dashboard ↓ 8. Dashboard detecta sucesso e mostra toast "Conectado com sucesso" ``` ## Componentes ### 1. Dashboard (`/app/dashboard/page.tsx`) Gera a oauth_url do Google diretamente no frontend: ```typescript const handleConnectGoogleCalendar = async () => { const oauthUrl = new URL("https://accounts.google.com/o/oauth2/v2/auth"); oauthUrl.searchParams.set("client_id", NEXT_PUBLIC_GOOGLE_CLIENT_ID); oauthUrl.searchParams.set("redirect_uri", `${origin}/api/google-calendar/callback`); oauthUrl.searchParams.set("state", user.id); oauthUrl.searchParams.set("scope", "https://www.googleapis.com/auth/calendar"); oauthUrl.searchParams.set("access_type", "offline"); oauthUrl.searchParams.set("prompt", "consent"); window.location.href = oauthUrl.toString(); }; ``` ### 2. Endpoint de Callback (`/app/api/google-calendar/callback/route.ts`) Este endpoint intercepta o callback do Google: ```typescript // Recebe: ?code=...&state=...&scope=... // 1. Salva no Supabase (portal.integrations) usando state = user_id // 2. Redireciona para n8n com mesmos parâmetros ``` **Responsabilidades:** - Receber callback do Google com parâmetros OAuth - Extrair user_id do state - Salvar status "connecting" no Supabase - Repassar TODOS os parâmetros para o n8n - Tratar erros do Google (error, error_description) ### 3. Credencial OAuth2 no n8n A credencial no n8n deve estar configurada com: - **Client ID**: do Google Cloud Console - **Client Secret**: do Google Cloud Console - **Authorization URL**: `https://accounts.google.com/o/oauth2/v2/auth` - **Access Token URL**: `https://oauth2.googleapis.com/token` - **Scope**: `https://www.googleapis.com/auth/calendar` - **Auth URI Query Parameters**: `access_type=offline&prompt=consent` (para obter refresh_token) ## Configuração ### 1. Google Cloud Console Adicione as seguintes URLs aos **Authorized redirect URIs**: **Desenvolvimento:** ``` http://localhost:3000/api/google-calendar/callback https://n8n.automatizase.com.br/rest/oauth2-credential/callback ``` **Produção:** ``` https://dashboard.automatizase.com.br/api/google-calendar/callback https://n8n.automatizase.com.br/rest/oauth2-credential/callback ``` **Importante:** Ambas URLs são necessárias porque: - A primeira intercepta o callback do Google - A segunda é para onde o dashboard redireciona (n8n processa) ### 2. Variáveis de Ambiente (.env.local) **Desenvolvimento (localhost):** ```bash # Google OAuth (mesmo Client ID do n8n) NEXT_PUBLIC_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com # URL base do n8n (sem trailing slash) N8N_BASE_URL=https://n8n.automatizase.com.br # URL do site (localhost em dev) NEXT_PUBLIC_SITE_URL=http://localhost:3000 ``` **Produção:** ```bash # Google OAuth (mesmo Client ID do n8n) NEXT_PUBLIC_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com # URL base do n8n (sem trailing slash) N8N_BASE_URL=https://n8n.automatizase.com.br # URL do site (domínio em produção) NEXT_PUBLIC_SITE_URL=https://dashboard.automatizase.com.br ``` **IMPORTANTE:** Use o **mesmo Client ID** que está configurado na credencial OAuth2 do n8n. Isso garante que os tokens gerados sejam compatíveis. ## Tabela Supabase ```sql -- portal.integrations CREATE TABLE IF NOT EXISTS portal.integrations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE, provider VARCHAR(50) NOT NULL, -- 'google_calendar' status VARCHAR(20) NOT NULL, -- 'connecting', 'connected', 'error' connected_at TIMESTAMPTZ, updated_at TIMESTAMPTZ DEFAULT NOW(), metadata JSONB, UNIQUE(user_id, provider) ); ``` ## Tratamento de Erros ### Erro no Google OAuth ``` Google redireciona: /api/google-calendar/callback?error=access_denied Dashboard redireciona: /dashboard?oauth_error=access_denied Dashboard mostra toast: "Erro ao conectar Google Calendar" ``` ### Erro ao Salvar no Supabase - Log do erro no console - Não bloqueia o fluxo (continua redirecionando para n8n) - Permite que OAuth funcione mesmo com falha no banco ### Erro no n8n ``` n8n redireciona: /dashboard?oauth_error=... Dashboard mostra toast: "Erro ao conectar Google Calendar" ``` ## Segurança 1. **State Parameter**: O n8n deve gerar `state` único e validar no callback 2. **HTTPS Only**: Todos os endpoints devem usar HTTPS em produção 3. **CORS**: Configurar CORS no n8n se necessário 4. **Validação**: Validar todos os parâmetros antes de redirecionar ## Logs e Debug ```typescript // Endpoint de callback loga: console.log("Redirecionando para n8n:", n8nCallbackUrl.toString()); console.error("Erro ao salvar no Supabase:", dbError); console.error("Erro no OAuth do Google:", error); ``` ## Diferenças do Fluxo Anterior ### Fluxo Anterior (Tentativa 1 - Não Funciona) - Dashboard trocava code por tokens diretamente - Dashboard tentava salvar credencial via API REST do n8n - BUG: n8n API REST valida schema OAuth2 de forma incorreta ### Fluxo Anterior (Tentativa 2 - Complexo) - Dashboard chamava webhook n8n para gerar oauth_url - n8n retornava oauth_url - Dashboard redirecionava para Google - PROBLEMA: Overhead desnecessário, n8n não precisa gerar URL ### Fluxo Atual (Funciona e é Simples) - Dashboard gera oauth_url do Google diretamente (sem chamar n8n) - Dashboard apenas intercepta callback e salva no banco - Dashboard redireciona para n8n processar OAuth - n8n faz toda a troca de tokens e salva na credencial - VANTAGEM: Simples, rápido, sem overhead, usa OAuth nativo do n8n ## Vantagens 1. ✅ Usa sistema OAuth2 nativo do n8n (sem bugs) 2. ✅ Permite salvar status no banco antes de processar 3. ✅ Mantém controle sobre experiência do usuário 4. ✅ n8n gerencia tokens automaticamente (refresh, revoke) 5. ✅ Simples de manter (apenas redirect, sem lógica complexa) ## Próximos Passos Após OAuth conectado, você pode: 1. Atualizar status para "connected" quando n8n confirmar 2. Adicionar webhook do n8n para notificar quando eventos de calendário ocorrem 3. Exibir calendários e eventos no dashboard 4. Permitir desconexão (revoke do OAuth)