TOKEN - Gerenciamento de Tokens JWT
O que é este Node?
O TOKEN é o node responsável por gerenciar tokens JWT (JSON Web Tokens) no Lumina Flow Builder. Ele permite gerar, verificar e decodificar tokens JWT para autenticação e autorização.
Por que este Node existe?
Tokens JWT são essenciais para autenticação stateless em sistemas modernos. O TOKEN existe para:
- Autenticação Stateless: Criar tokens auto-contidos que não requerem armazenamento em servidor
- Segurança de APIs: Proteger endpoints de API com tokens assinados criptograficamente
- Autorização: Incluir claims e permissões diretamente no token
- Expiração Automática: Definir tempo de vida dos tokens para maior segurança
- Portabilidade: Usar tokens que funcionam em diferentes sistemas e linguagens
Como funciona internamente?
Quando o TOKEN é executado, o sistema:
- Identifica operação: Determina se deve gerar, verificar ou decodificar token
- Operação Generate:
- Recebe payload (dados a incluir no token)
- Assina com secret usando algoritmo HS256
- Define tempo de expiração
- Retorna token JWT completo
- Operação Verify:
- Recebe token e secret
- Verifica assinatura criptográfica
- Valida expiração
- Retorna sucesso ou falha
- Operação Decode:
- Extrai header e payload do token
- NÃO verifica assinatura (apenas leitura)
- Retorna dados decodificados
Código interno (security-executor.service.ts:150-168):
private async executeToken(parameters: any, context: any): Promise<any> {
const { operation, payload, secret, token, expiresIn } = parameters;
this.logger.log(`🎫 TOKEN - Operation: ${operation}`);
switch (operation) {
case 'generate':
return this.generateJWT(payload, secret, expiresIn);
case 'verify':
return this.verifyJWT(token, secret);
case 'decode':
return this.decodeJWT(token);
default:
throw new Error(`Unsupported token operation: ${operation}`);
}
}
Quando você DEVE usar este Node?
Use TOKEN sempre que precisar de autenticação baseada em tokens JWT:
Casos de uso
- API Authentication: "Preciso gerar tokens para autenticar requisições de API"
- Single Sign-On: "Preciso criar token que funcione em múltiplos sistemas"
- Sessões sem Estado: "Preciso autenticar sem armazenar sessões no servidor"
- Autorização Granular: "Preciso incluir roles e permissões no token"
- Integração de Terceiros: "Preciso validar tokens de serviços externos"
Quando NÃO usar TOKEN
- Dados Sensíveis: Use ENCRYPT ao invés de TOKEN (JWT é apenas codificado, não criptografado)
- Autenticação de Dois Fatores: Use 2FA ao invés de TOKEN
- OAuth Social Login: Use OAUTH ao invés de TOKEN direto
Parâmetros Detalhados
operation (string, obrigatório)
O que é: Define qual operação será executada com o token JWT.
Valores possíveis:
- generate: Gera novo token JWT
- verify: Verifica validade e assinatura de token
- decode: Decodifica token sem verificar assinatura
Flow completo para testar (Generate):
{
"name": "Teste TOKEN - Generate",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "token_1",
"type": "token",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Gerar Token",
"parameters": {
"operation": "generate",
"payload": {
"userId": "12345",
"username": "jose.roberto",
"role": "admin"
},
"secret": "meu-secret-super-seguro",
"expiresIn": "1h"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Mostrar Token",
"parameters": {
"message": "Token gerado: {{token_1.token}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "token_1" },
{ "source": "token_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Gera um token JWT. Deve retornar token no formato eyJhbGc...
payload (object, obrigatório para generate)
O que é: Dados que serão incluídos no token JWT. Pode conter qualquer informação JSON.
Dados comuns: userId, username, email, role, permissions
Flow completo para testar:
{
"name": "Teste TOKEN - Payload",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 300, "y": 100 },
"data": {
"label": "User ID",
"parameters": {
"message": "Digite o user ID:",
"variableName": "userId"
}
}
},
{
"id": "input_2",
"type": "input",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Username",
"parameters": {
"message": "Digite o username:",
"variableName": "username"
}
}
},
{
"id": "token_1",
"type": "token",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Gerar Token",
"parameters": {
"operation": "generate",
"payload": {
"userId": "{{userId}}",
"username": "{{username}}"
},
"secret": "meu-secret"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Sucesso",
"parameters": {
"message": "Token criado para {{username}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1100, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "input_2" },
{ "source": "input_2", "target": "token_1" },
{ "source": "token_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Digite userId e username. O token gerado conterá esses dados.
secret (string, obrigatório para generate e verify)
O que é: Chave secreta usada para assinar e verificar tokens JWT. DEVE ser mantida em segredo.
Flow completo para testar:
{
"name": "Teste TOKEN - 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": "Secret",
"parameters": {
"name": "jwtSecret",
"value": "minha-chave-secreta-super-segura-123"
}
}
},
{
"id": "token_1",
"type": "token",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Gerar",
"parameters": {
"operation": "generate",
"payload": { "user": "teste" },
"secret": "{{jwtSecret}}"
}
}
},
{
"id": "token_2",
"type": "token",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Verificar",
"parameters": {
"operation": "verify",
"token": "{{token_1.token}}",
"secret": "{{jwtSecret}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Resultado",
"parameters": {
"message": "Token válido: {{token_2.valid}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1100, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "variable_1" },
{ "source": "variable_1", "target": "token_1" },
{ "source": "token_1", "target": "token_2" },
{ "source": "token_2", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Gera e verifica token com mesmo secret. Deve retornar valid: true.
token (string, obrigatório para verify e decode)
O que é: Token JWT a ser verificado ou decodificado.
Flow completo para testar:
{
"name": "Teste TOKEN - Verify",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "token_1",
"type": "token",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Gerar Token",
"parameters": {
"operation": "generate",
"payload": { "userId": "123" },
"secret": "meu-secret"
}
}
},
{
"id": "token_2",
"type": "token",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Verificar Token",
"parameters": {
"operation": "verify",
"token": "{{token_1.token}}",
"secret": "meu-secret"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Status",
"parameters": {
"message": "Válido: {{token_2.valid}}, User: {{token_2.payload.userId}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "token_1" },
{ "source": "token_1", "target": "token_2" },
{ "source": "token_2", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Gera e verifica token. Deve retornar valid: true e payload.
expiresIn (string, opcional)
O que é: Tempo de expiração do token.
Padrão: "1h"
Valores suportados: "1h", "24h", "7d", "30d", "1y"
Flow completo para testar:
{
"name": "Teste TOKEN - ExpiresIn",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "token_1",
"type": "token",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Token Curto",
"parameters": {
"operation": "generate",
"payload": { "type": "temporary" },
"secret": "secret",
"expiresIn": "5m"
}
}
},
{
"id": "token_2",
"type": "token",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Token Longo",
"parameters": {
"operation": "generate",
"payload": { "type": "permanent" },
"secret": "secret",
"expiresIn": "30d"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Expirações",
"parameters": {
"message": "Temp expira: {{token_1.expiresAt}}\nPerm expira: {{token_2.expiresAt}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "token_1" },
{ "source": "start_1", "target": "token_2" },
{ "source": "token_1", "target": "message_1" },
{ "source": "token_2", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Gera tokens com diferentes expirações. Deve mostrar datas diferentes.
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| operation | string | Sim | Operação: generate, verify, decode |
| payload | object | Condicional | Dados do token (obrigatório para generate) |
| secret | string | Condicional | Secret para assinar/verificar (obrigatório para generate/verify) |
| token | string | Condicional | Token JWT (obrigatório para verify/decode) |
| expiresIn | string | Não | Tempo de expiração (padrão: 1h) |
Exemplo 1: Sistema Completo de Autenticação JWT
Objetivo: Demonstrar geração, verificação e uso de tokens JWT
JSON para Importar
{
"name": "Sistema JWT Completo",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Login",
"parameters": {
"message": "Digite seu username:",
"variableName": "username"
}
}
},
{
"id": "token_1",
"type": "token",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Gerar Token",
"parameters": {
"operation": "generate",
"payload": {
"username": "{{username}}",
"role": "user",
"permissions": ["read", "write"]
},
"secret": "jwt-secret-key-123",
"expiresIn": "24h"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Token Gerado",
"parameters": {
"message": "Token JWT criado! Expira em: {{token_1.expiresAt}}"
}
}
},
{
"id": "input_2",
"type": "input",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Fazer Requisição",
"parameters": {
"message": "Digite 'api' para fazer requisição:",
"variableName": "action"
}
}
},
{
"id": "token_2",
"type": "token",
"position": { "x": 1100, "y": 100 },
"data": {
"label": "Validar Token",
"parameters": {
"operation": "verify",
"token": "{{token_1.token}}",
"secret": "jwt-secret-key-123"
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 1300, "y": 100 },
"data": {
"label": "Token Válido?",
"parameters": {
"condition": "{{token_2.valid}} == true"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 1500, "y": 50 },
"data": {
"label": "Acesso Permitido",
"parameters": {
"message": "Requisição autorizada para {{token_2.payload.username}}"
}
}
},
{
"id": "message_3",
"type": "message",
"position": { "x": 1500, "y": 150 },
"data": {
"label": "Acesso Negado",
"parameters": {
"message": "Token inválido ou expirado!"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "token_1" },
{ "source": "token_1", "target": "message_1" },
{ "source": "message_1", "target": "input_2" },
{ "source": "input_2", "target": "token_2" },
{ "source": "token_2", "target": "condition_1" },
{ "source": "condition_1", "target": "message_2", "label": "true" },
{ "source": "condition_1", "target": "message_3", "label": "false" },
{ "source": "message_2", "target": "end_1" },
{ "source": "message_3", "target": "end_1" }
]
}
Saída esperada:
Sistema: Digite seu username:
Usuário: jose.roberto
Sistema: Token JWT criado! Expira em: 2025-01-16T10:30:00.000Z
Sistema: Digite 'api' para fazer requisição:
Usuário: api
Sistema: Requisição autorizada para jose.roberto
Exemplo 2: Decodificar Token sem Verificar
Objetivo: Demonstrar leitura de dados do token sem validar assinatura
JSON para Importar
{
"name": "Decodificar Token JWT",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "token_1",
"type": "token",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Gerar Token",
"parameters": {
"operation": "generate",
"payload": {
"userId": "12345",
"username": "jose.roberto",
"role": "admin",
"email": "jose@example.com"
},
"secret": "meu-secret"
}
}
},
{
"id": "token_2",
"type": "token",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Decodificar",
"parameters": {
"operation": "decode",
"token": "{{token_1.token}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Dados Extraídos",
"parameters": {
"message": "User: {{token_2.payload.username}}\nRole: {{token_2.payload.role}}\nEmail: {{token_2.payload.email}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "token_1" },
{ "source": "token_1", "target": "token_2" },
{ "source": "token_2", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Saída esperada:
Sistema: User: jose.roberto
Role: admin
Email: jose@example.com
Exemplo 3: Autorização Baseada em Roles
Objetivo: Demonstrar controle de acesso usando claims do token
JSON para Importar
{
"name": "Autorização por Roles no Token",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Selecionar Role",
"parameters": {
"message": "Digite seu role (admin/user/guest):",
"variableName": "userRole"
}
}
},
{
"id": "token_1",
"type": "token",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Criar Token",
"parameters": {
"operation": "generate",
"payload": {
"username": "usuario",
"role": "{{userRole}}"
},
"secret": "secret-key"
}
}
},
{
"id": "token_2",
"type": "token",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Verificar Token",
"parameters": {
"operation": "verify",
"token": "{{token_1.token}}",
"secret": "secret-key"
}
}
},
{
"id": "condition_1",
"type": "condition",
"position": { "x": 900, "y": 100 },
"data": {
"label": "É Admin?",
"parameters": {
"condition": "{{token_2.payload.role}} == 'admin'"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 1100, "y": 50 },
"data": {
"label": "Admin",
"parameters": {
"message": "Acesso total concedido (Admin)"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 1100, "y": 150 },
"data": {
"label": "Outros",
"parameters": {
"message": "Acesso limitado (Role: {{token_2.payload.role}})"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1300, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "token_1" },
{ "source": "token_1", "target": "token_2" },
{ "source": "token_2", "target": "condition_1" },
{ "source": "condition_1", "target": "message_1", "label": "true" },
{ "source": "condition_1", "target": "message_2", "label": "false" },
{ "source": "message_1", "target": "end_1" },
{ "source": "message_2", "target": "end_1" }
]
}
Saída esperada:
Sistema: Digite seu role (admin/user/guest):
Usuário: admin
Sistema: Acesso total concedido (Admin)
Resposta do Node
Generate:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresAt": "2025-01-15T11:30:00.000Z",
"payload": {
"userId": "12345",
"username": "jose.roberto"
}
}
Verify (válido):
{
"success": true,
"valid": true,
"payload": {
"userId": "12345",
"username": "jose.roberto",
"iat": 1705317000,
"exp": 1705320600
},
"timestamp": "2025-01-15T10:30:00.000Z"
}
Decode:
{
"success": true,
"header": {
"alg": "HS256",
"typ": "JWT"
},
"payload": {
"userId": "12345",
"username": "jose.roberto",
"iat": 1705317000,
"exp": 1705320600
},
"timestamp": "2025-01-15T10:30:00.000Z"
}
Boas Práticas
✅ SIM:
- Use tokens JWT para APIs stateless
- Defina expiração apropriada (1h para tokens de acesso)
- Inclua apenas dados necessários no payload
- Use secret forte e armazenado em variável de ambiente
- Verifique assinatura antes de confiar no token
- Implemente refresh tokens para sessões longas
❌ NÃO:
- Não inclua dados sensíveis no payload (JWT é apenas codificado)
- Não use tokens sem expiração
- Não compartilhe secret entre sistemas diferentes
- Não confie em tokens sem verificação
- Não use secrets curtos ou previsíveis
- Não armazene tokens em localStorage (use httpOnly cookies)
Dicas
💡 Dica 1: JWT não é criptografado, apenas codificado. Qualquer um pode ler o payload sem a chave
💡 Dica 2: Use operation "decode" quando só precisa ler dados, "verify" quando precisa validar autenticidade
💡 Dica 3: Combine TOKEN com CONDITION para criar fluxos de autorização baseados em roles e permissões
💡 Dica 4: Para máxima segurança, use tokens de curta duração (5-15min) com refresh tokens
💡 Dica 5: Inclua timestamp ou nonce no payload para prevenir replay attacks
Próximo Node
→ AUTH - Autenticação e gerenciamento de sessão → 2FA - Autenticação de dois fatores → OAUTH - OAuth 2.0 flow