- Implemented a bash script to test n8n API and retrieve credential schemas. - Added types for API responses, Google Calendar, and WhatsApp instances. - Configured Vitest for testing with React and added setup for testing-library.
223 lines
7.2 KiB
Markdown
223 lines
7.2 KiB
Markdown
# 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)
|