OAUTH - OAuth 2.0 Flow
O que é este Node?
O OAUTH é o node responsável por implementar fluxos OAuth 2.0 no Lumina Flow Builder. Ele permite integração com provedores como Google, Facebook, GitHub e Microsoft para autenticação social.
Por que este Node existe?
OAuth 2.0 é o padrão da indústria para autorização delegada. O OAUTH existe para:
- Social Login: Permitir login com contas Google, Facebook, GitHub, Microsoft
- Autorização Segura: Obter acesso a recursos sem expor credenciais do usuário
- Padrão da Indústria: Implementar protocolo OAuth 2.0 (RFC 6749)
- Tokens de Acesso: Gerenciar access tokens e refresh tokens
- Múltiplos Provedores: Suportar diferentes provedores OAuth com código unificado
Como funciona internamente?
Quando o OAUTH é executado, o sistema:
- Identifica operação: Determina se deve gerar URL de autorização, trocar código por token ou renovar token
- Operação Get Auth URL:
- Monta URL de autorização do provedor
- Adiciona client_id, redirect_uri, scope e state
- Retorna URL para redirecionar usuário
- Operação Exchange Code:
- Recebe código de autorização da callback
- Faz POST para endpoint de token do provedor
- Troca código por access_token e refresh_token
- Retorna tokens para uso
- Operação Refresh Token:
- Usa refresh_token para obter novo access_token
- Evita re-autenticação do usuário
- Retorna novo access_token
Código interno (security-executor.service.ts:196-214):
private async executeOAuth(parameters: any, context: any): Promise<any> {
const { provider, operation, clientId, clientSecret, redirectUri, code, scope } = parameters;
this.logger.log(`🔗 OAUTH - Provider: ${provider}, Operation: ${operation}`);
switch (operation) {
case 'get_auth_url':
return this.getOAuthAuthURL(provider, clientId, redirectUri, scope);
case 'exchange_code':
return this.exchangeOAuthCode(provider, code, clientId, clientSecret, redirectUri);
case 'refresh_token':
return this.refreshOAuthToken(provider, parameters.refreshToken, clientId, clientSecret);
default:
throw new Error(`Unsupported OAuth operation: ${operation}`);
}
}
Quando você DEVE usar este Node?
Use OAUTH sempre que precisar de autenticação social ou autorização delegada:
Casos de uso
- Login Social: "Preciso permitir login com conta Google/Facebook"
- Integração de APIs: "Preciso acessar Google Drive do usuário"
- Single Sign-On: "Preciso autenticar usando Microsoft Azure AD"
- Importação de Dados: "Preciso importar contatos do Gmail do usuário"
- Publicação em Redes Sociais: "Preciso postar no Facebook em nome do usuário"
Quando NÃO usar OAUTH
- Autenticação Simples: Use AUTH para login com username/senha
- APIs com API Key: Use HTTP request direto com headers
- Autenticação Interna: Use TOKEN para JWT interno
Parâmetros Detalhados
provider (string, obrigatório)
O que é: Provedor OAuth 2.0 a ser utilizado.
Valores suportados:
- google: Google OAuth 2.0
- facebook: Facebook Login
- github: GitHub OAuth
- microsoft: Microsoft Azure AD
Flow completo para testar:
{
"name": "Teste OAUTH - Provider",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "oauth_1",
"type": "oauth",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Google Auth URL",
"parameters": {
"provider": "google",
"operation": "get_auth_url",
"clientId": "seu-client-id.apps.googleusercontent.com",
"redirectUri": "https://lumina.app.br/callback"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Mostrar URL",
"parameters": {
"message": "Redirecione para: {{oauth_1.authUrl}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "oauth_1" },
{ "source": "oauth_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Gera URL de autorização do Google. Deve retornar URL começando com accounts.google.com.
operation (string, obrigatório)
O que é: Define qual operação OAuth será executada.
Valores possíveis:
- get_auth_url: Gera URL para redirecionar usuário
- exchange_code: Troca código de autorização por tokens
- refresh_token: Renova access token usando refresh token
Flow completo para testar:
{
"name": "Teste OAUTH - Operations",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "oauth_1",
"type": "oauth",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Step 1: Auth URL",
"parameters": {
"provider": "google",
"operation": "get_auth_url",
"clientId": "client-id",
"redirectUri": "https://app.com/callback",
"scope": "email profile"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Instruções",
"parameters": {
"message": "1. Acesse: {{oauth_1.authUrl}}\n2. Autorize\n3. Copie código da URL"
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Código",
"parameters": {
"message": "Cole código de autorização:",
"variableName": "authCode"
}
}
},
{
"id": "oauth_2",
"type": "oauth",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Step 2: Exchange",
"parameters": {
"provider": "google",
"operation": "exchange_code",
"code": "{{authCode}}",
"clientId": "client-id",
"clientSecret": "client-secret",
"redirectUri": "https://app.com/callback"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 1100, "y": 100 },
"data": {
"label": "Tokens",
"parameters": {
"message": "Access Token: {{oauth_2.accessToken}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1300, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "oauth_1" },
{ "source": "oauth_1", "target": "message_1" },
{ "source": "message_1", "target": "input_1" },
{ "source": "input_1", "target": "oauth_2" },
{ "source": "oauth_2", "target": "message_2" },
{ "source": "message_2", "target": "end_1" }
]
}
Teste: Fluxo completo OAuth. Gera URL, usuário autoriza, código é trocado por tokens.
clientId (string, obrigatório)
O que é: ID da aplicação OAuth registrada no provedor (Google Console, Facebook App, etc).
Flow completo para testar:
{
"name": "Teste OAUTH - Client ID",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Config OAuth",
"parameters": {
"name": "googleClientId",
"value": "123456789-abc.apps.googleusercontent.com"
}
}
},
{
"id": "oauth_1",
"type": "oauth",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Usar Client ID",
"parameters": {
"provider": "google",
"operation": "get_auth_url",
"clientId": "{{googleClientId}}",
"redirectUri": "https://app.com/callback"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "URL Gerada",
"parameters": {
"message": "URL OAuth configurada com Client ID"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "variable_1" },
{ "source": "variable_1", "target": "oauth_1" },
{ "source": "oauth_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Usa Client ID em variável. Deve gerar URL OAuth válida.
clientSecret (string, obrigatório para exchange_code e refresh_token)
O que é: Secret da aplicação OAuth. DEVE ser mantido em segredo no servidor.
Flow completo para testar:
{
"name": "Teste OAUTH - Client Secret",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Secrets",
"parameters": {
"name": "secrets",
"value": "{\"clientId\": \"id123\", \"clientSecret\": \"secret456\"}"
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Auth Code",
"parameters": {
"message": "Cole código OAuth:",
"variableName": "code"
}
}
},
{
"id": "oauth_1",
"type": "oauth",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Exchange com Secret",
"parameters": {
"provider": "google",
"operation": "exchange_code",
"code": "{{code}}",
"clientId": "id123",
"clientSecret": "secret456",
"redirectUri": "https://app.com/callback"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Tokens Obtidos",
"parameters": {
"message": "Tokens recebidos com sucesso!"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1100, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "variable_1" },
{ "source": "variable_1", "target": "input_1" },
{ "source": "input_1", "target": "oauth_1" },
{ "source": "oauth_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Troca código por tokens usando client secret. Deve retornar access_token.
redirectUri (string, obrigatório)
O que é: URL de callback registrada na aplicação OAuth. Provedor redireciona para aqui após autorização.
Flow completo para testar:
{
"name": "Teste OAUTH - Redirect URI",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Configurar Redirect",
"parameters": {
"name": "callbackUrl",
"value": "https://lumina.app.br/oauth/callback"
}
}
},
{
"id": "oauth_1",
"type": "oauth",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Gerar Auth URL",
"parameters": {
"provider": "github",
"operation": "get_auth_url",
"clientId": "github-client-id",
"redirectUri": "{{callbackUrl}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Info",
"parameters": {
"message": "Após autorizar, será redirecionado para: {{callbackUrl}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "variable_1" },
{ "source": "variable_1", "target": "oauth_1" },
{ "source": "oauth_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Configura redirect URI. URL OAuth incluirá esse callback.
scope (string, opcional)
O que é: Escopos (permissões) solicitados ao usuário.
Padrão: "openid email profile"
Valores comuns: - Google: "email profile https://www.googleapis.com/auth/drive" - GitHub: "user repo" - Facebook: "email public_profile"
Flow completo para testar:
{
"name": "Teste OAUTH - Scope",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "oauth_1",
"type": "oauth",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Solicitar Drive",
"parameters": {
"provider": "google",
"operation": "get_auth_url",
"clientId": "client-id",
"redirectUri": "https://app.com/callback",
"scope": "email profile https://www.googleapis.com/auth/drive.readonly"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Permissões",
"parameters": {
"message": "Solicitando acesso a: Email, Perfil e Google Drive (leitura)"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "oauth_1" },
{ "source": "oauth_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Solicita permissões específicas. Usuário verá tela de consentimento com essas permissões.
code (string, obrigatório para exchange_code)
O que é: Código de autorização recebido na URL de callback após usuário autorizar.
Flow completo para testar:
{
"name": "Teste OAUTH - Exchange Code",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "message_1",
"type": "message",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Simular Callback",
"parameters": {
"message": "Simulando callback: ?code=abc123xyz..."
}
}
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Extrair Code",
"parameters": {
"name": "authCode",
"value": "abc123xyz"
}
}
},
{
"id": "oauth_1",
"type": "oauth",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Trocar por Token",
"parameters": {
"provider": "google",
"operation": "exchange_code",
"code": "{{authCode}}",
"clientId": "client-id",
"clientSecret": "client-secret",
"redirectUri": "https://app.com/callback"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Sucesso",
"parameters": {
"message": "Access Token: {{oauth_1.accessToken}}\nExpira em: {{oauth_1.expiresIn}}s"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1100, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "message_1" },
{ "source": "message_1", "target": "variable_1" },
{ "source": "variable_1", "target": "oauth_1" },
{ "source": "oauth_1", "target": "message_2" },
{ "source": "message_2", "target": "end_1" }
]
}
Teste: Troca código por access token. Deve retornar tokens válidos.
refreshToken (string, obrigatório para refresh_token)
O que é: Refresh token recebido no exchange_code, usado para obter novos access tokens.
Flow completo para testar:
{
"name": "Teste OAUTH - Refresh Token",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Salvar Refresh Token",
"parameters": {
"name": "refreshToken",
"value": "refresh_token_abc123xyz"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Cenário",
"parameters": {
"message": "Access token expirou... Renovando..."
}
}
},
{
"id": "oauth_1",
"type": "oauth",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Renovar Token",
"parameters": {
"provider": "google",
"operation": "refresh_token",
"refreshToken": "{{refreshToken}}",
"clientId": "client-id",
"clientSecret": "client-secret"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Token Renovado",
"parameters": {
"message": "Novo access token obtido sem re-autenticação!"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1100, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "variable_1" },
{ "source": "variable_1", "target": "message_1" },
{ "source": "message_1", "target": "oauth_1" },
{ "source": "oauth_1", "target": "message_2" },
{ "source": "message_2", "target": "end_1" }
]
}
Teste: Renova access token usando refresh token. Não precisa re-autenticar usuário.
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| provider | string | Sim | Provedor OAuth: google, facebook, github, microsoft |
| operation | string | Sim | Operação: get_auth_url, exchange_code, refresh_token |
| clientId | string | Sim | ID da aplicação OAuth |
| clientSecret | string | Condicional | Secret da aplicação (obrigatório para exchange_code e refresh_token) |
| redirectUri | string | Sim | URL de callback registrada |
| scope | string | Não | Permissões solicitadas (padrão: "openid email profile") |
| code | string | Condicional | Código de autorização (obrigatório para exchange_code) |
| refreshToken | string | Condicional | Refresh token (obrigatório para refresh_token) |
Exemplo 1: Login com Google Completo
Objetivo: Demonstrar fluxo completo de login com Google OAuth
JSON para Importar
{
"name": "Login com Google OAuth",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "message_1",
"type": "message",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Boas-vindas",
"parameters": {
"message": "Bem-vindo! Faça login com sua conta Google."
}
}
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 500, "y": 100 },
"data": {
"label": "OAuth Config",
"parameters": {
"name": "oauthConfig",
"value": "{\"clientId\": \"123-abc.apps.googleusercontent.com\", \"clientSecret\": \"secret123\", \"redirectUri\": \"https://lumina.app.br/callback\"}"
}
}
},
{
"id": "oauth_1",
"type": "oauth",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Gerar Auth URL",
"parameters": {
"provider": "google",
"operation": "get_auth_url",
"clientId": "123-abc.apps.googleusercontent.com",
"redirectUri": "https://lumina.app.br/callback",
"scope": "email profile"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Redirecionar",
"parameters": {
"message": "Redirecionando para Google... {{oauth_1.authUrl}}"
}
}
},
{
"id": "message_3",
"type": "message",
"position": { "x": 1100, "y": 100 },
"data": {
"label": "Aguardar Callback",
"parameters": {
"message": "Aguardando autorização..."
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 1300, "y": 100 },
"data": {
"label": "Código Recebido",
"parameters": {
"message": "Sistema recebeu código. Processando...\nCole código:",
"variableName": "authCode"
}
}
},
{
"id": "oauth_2",
"type": "oauth",
"position": { "x": 1500, "y": 100 },
"data": {
"label": "Exchange Code",
"parameters": {
"provider": "google",
"operation": "exchange_code",
"code": "{{authCode}}",
"clientId": "123-abc.apps.googleusercontent.com",
"clientSecret": "secret123",
"redirectUri": "https://lumina.app.br/callback"
}
}
},
{
"id": "message_4",
"type": "message",
"position": { "x": 1700, "y": 100 },
"data": {
"label": "Login Completo",
"parameters": {
"message": "Login realizado com sucesso!\nAccess Token: {{oauth_2.accessToken}}\nToken Type: {{oauth_2.tokenType}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "message_1" },
{ "source": "message_1", "target": "variable_1" },
{ "source": "variable_1", "target": "oauth_1" },
{ "source": "oauth_1", "target": "message_2" },
{ "source": "message_2", "target": "message_3" },
{ "source": "message_3", "target": "input_1" },
{ "source": "input_1", "target": "oauth_2" },
{ "source": "oauth_2", "target": "message_4" },
{ "source": "message_4", "target": "end_1" }
]
}
Saída esperada:
Sistema: Bem-vindo! Faça login com sua conta Google.
Sistema: Redirecionando para Google... https://accounts.google.com/o/oauth2/v2/auth?...
Sistema: Aguardando autorização...
Sistema: Sistema recebeu código. Processando...
Cole código:
Usuário: abc123xyz
Sistema: Login realizado com sucesso!
Access Token: ya29.a0AfH6SMB...
Token Type: Bearer
Exemplo 2: Múltiplos Provedores OAuth
Objetivo: Demonstrar suporte a diferentes provedores OAuth
JSON para Importar
{
"name": "Múltiplos Provedores OAuth",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "message_1",
"type": "message",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Menu",
"parameters": {
"message": "Escolha provedor:\n1. Google\n2. GitHub\n3. Microsoft"
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Escolha",
"parameters": {
"message": "Digite número (1-3):",
"variableName": "escolha"
}
}
},
{
"id": "switch_1",
"type": "switch",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Selecionar Provedor",
"parameters": {
"variable": "escolha",
"cases": [
{ "value": "1", "target": "oauth_google" },
{ "value": "2", "target": "oauth_github" },
{ "value": "3", "target": "oauth_microsoft" }
]
}
}
},
{
"id": "oauth_google",
"type": "oauth",
"position": { "x": 900, "y": 50 },
"data": {
"label": "Google",
"parameters": {
"provider": "google",
"operation": "get_auth_url",
"clientId": "google-client-id",
"redirectUri": "https://app.com/callback"
}
}
},
{
"id": "oauth_github",
"type": "oauth",
"position": { "x": 900, "y": 100 },
"data": {
"label": "GitHub",
"parameters": {
"provider": "github",
"operation": "get_auth_url",
"clientId": "github-client-id",
"redirectUri": "https://app.com/callback"
}
}
},
{
"id": "oauth_microsoft",
"type": "oauth",
"position": { "x": 900, "y": 150 },
"data": {
"label": "Microsoft",
"parameters": {
"provider": "microsoft",
"operation": "get_auth_url",
"clientId": "microsoft-client-id",
"redirectUri": "https://app.com/callback"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 1100, "y": 100 },
"data": {
"label": "Auth URL",
"parameters": {
"message": "Acesse para autenticar: {{authUrl}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1300, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "message_1" },
{ "source": "message_1", "target": "input_1" },
{ "source": "input_1", "target": "switch_1" },
{ "source": "oauth_google", "target": "message_2" },
{ "source": "oauth_github", "target": "message_2" },
{ "source": "oauth_microsoft", "target": "message_2" },
{ "source": "message_2", "target": "end_1" }
]
}
Saída esperada:
Sistema: Escolha provedor:
1. Google
2. GitHub
3. Microsoft
Sistema: Digite número (1-3):
Usuário: 2
Sistema: Acesse para autenticar: https://github.com/login/oauth/authorize?...
Exemplo 3: Gerenciamento de Tokens com Refresh
Objetivo: Demonstrar renovação automática de access tokens
JSON para Importar
{
"name": "Gerenciamento de Tokens OAuth",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Tokens Salvos",
"parameters": {
"name": "tokens",
"value": "{\"accessToken\": \"ya29.old\", \"refreshToken\": \"refresh_abc123\", \"expiresAt\": \"2025-01-15T10:00:00Z\"}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Verificar Expiração",
"parameters": {
"message": "Access token expira em: {{tokens.expiresAt}}"
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Token Expirado?",
"parameters": {
"condition": "true"
}
}
},
{
"id": "oauth_1",
"type": "oauth",
"position": { "x": 900, "y": 50 },
"data": {
"label": "Renovar Token",
"parameters": {
"provider": "google",
"operation": "refresh_token",
"refreshToken": "refresh_abc123",
"clientId": "client-id",
"clientSecret": "client-secret"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 1100, "y": 50 },
"data": {
"label": "Token Renovado",
"parameters": {
"message": "Novo access token obtido automaticamente!"
}
}
},
{
"id": "message_3",
"type": "message",
"position": { "x": 900, "y": 150 },
"data": {
"label": "Token Válido",
"parameters": {
"message": "Access token ainda válido. Usando token atual."
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1300, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "variable_1" },
{ "source": "variable_1", "target": "message_1" },
{ "source": "message_1", "target": "condition_1" },
{ "source": "condition_1", "target": "oauth_1", "label": "true" },
{ "source": "condition_1", "target": "message_3", "label": "false" },
{ "source": "oauth_1", "target": "message_2" },
{ "source": "message_2", "target": "end_1" },
{ "source": "message_3", "target": "end_1" }
]
}
Saída esperada:
Sistema: Access token expira em: 2025-01-15T10:00:00Z
Sistema: Novo access token obtido automaticamente!
Resposta do Node
Get Auth URL:
{
"success": true,
"action": "oauth_auth_url_generated",
"provider": "google",
"authUrl": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&redirect_uri=...&scope=...&response_type=code&state=abc123",
"timestamp": "2025-01-15T10:30:00.000Z"
}
Exchange Code:
{
"success": true,
"action": "oauth_code_exchanged",
"provider": "google",
"accessToken": "ya29.a0AfH6SMB...",
"refreshToken": "1//0gHZ9K3yQ-abc...",
"expiresIn": 3600,
"tokenType": "Bearer",
"timestamp": "2025-01-15T10:30:00.000Z"
}
Refresh Token:
{
"success": true,
"action": "oauth_token_refreshed",
"provider": "google",
"message": "Token refresh functionality implemented",
"timestamp": "2025-01-15T10:30:00.000Z"
}
Boas Práticas
✅ SIM:
- Armazene client secret em variáveis de ambiente, NUNCA no código
- Use HTTPS obrigatoriamente em redirect_uri (produção)
- Solicite apenas scopes necessários (princípio do menor privilégio)
- Armazene refresh tokens criptografados no banco de dados
- Implemente renovação automática de access tokens antes da expiração
- Valide parâmetro state para prevenir CSRF attacks
❌ NÃO:
- Não exponha client secret no frontend ou logs
- Não use HTTP em redirect_uri (apenas desenvolvimento local)
- Não solicite todos os scopes disponíveis
- Não armazene tokens em localStorage (use httpOnly cookies)
- Não ignore erros de OAuth (log e trate adequadamente)
- Não compartilhe client credentials entre ambientes (dev/prod)
Dicas
💡 Dica 1: Combine OAUTH com AUTH para criar fluxo híbrido (login social + tradicional)
💡 Dica 2: Use parâmetro state para manter contexto entre redirecionamento e callback
💡 Dica 3: Implemente tratamento de erro para quando usuário nega permissões
💡 Dica 4: Armazene timestamp de expiração e renove token 5 minutos antes
💡 Dica 5: Para produção, registre redirect_uri exata no console do provedor (sem wildcards)
Próximo Node
→ AUTH - Autenticação e gerenciamento de sessão → TOKEN - Gerenciamento de tokens JWT → 2FA - Autenticação de dois fatores