Pular para conteúdo

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:

  1. Social Login: Permitir login com contas Google, Facebook, GitHub, Microsoft
  2. Autorização Segura: Obter acesso a recursos sem expor credenciais do usuário
  3. Padrão da Indústria: Implementar protocolo OAuth 2.0 (RFC 6749)
  4. Tokens de Acesso: Gerenciar access tokens e refresh tokens
  5. Múltiplos Provedores: Suportar diferentes provedores OAuth com código unificado

Como funciona internamente?

Quando o OAUTH é executado, o sistema:

  1. Identifica operação: Determina se deve gerar URL de autorização, trocar código por token ou renovar token
  2. Operação Get Auth URL:
  3. Monta URL de autorização do provedor
  4. Adiciona client_id, redirect_uri, scope e state
  5. Retorna URL para redirecionar usuário
  6. Operação Exchange Code:
  7. Recebe código de autorização da callback
  8. Faz POST para endpoint de token do provedor
  9. Troca código por access_token e refresh_token
  10. Retorna tokens para uso
  11. Operação Refresh Token:
  12. Usa refresh_token para obter novo access_token
  13. Evita re-autenticação do usuário
  14. 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

  1. Login Social: "Preciso permitir login com conta Google/Facebook"
  2. Integração de APIs: "Preciso acessar Google Drive do usuário"
  3. Single Sign-On: "Preciso autenticar usando Microsoft Azure AD"
  4. Importação de Dados: "Preciso importar contatos do Gmail do usuário"
  5. 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