Obtendo um token gerado

Describe the problem/error/question

What is the error message (if any)? Not an error. This is a “how do I” question.

I know I’m doing this insecurely. This question is trying to rectify that. I have this workflow to generate a bearer token if the expiration time has lapsed. I want to use stored username/password, and if possible, store the bearer token until it needs to be replaced.

The workflow gets the username and password, along with the current bearer token, it’s expiration from a local store.

If the bearer token is expired, it uses an http node to call the server to have it generate a new token.

Finally, it returns the valid token to the calling workflow. I use this for multiple clients, so I would like to be able to specify which credentials it will be using when I call this workflow.

The purpose of this post is to secure the credentials. Since I use this for many clients, any solution should be able to call the appropriate credentials.

Please share your workflow

Share the output returned by the last node

This is the bearer token (expired!) returned by the API server.


[
  {
    "mosyle": 
    {
      "AuthToken": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE3Nzg3ODMxMDEsImV4cCI6MTc3ODg2OTUwMSwiaXNzIjoiTW9zeWxlIiwiZGF0YSI6eyJWWE5sY2tsRSI6Ik5qVTNOak15TWc9PSIsIlpXMWhhV3c9IjoiYmpodVFHcDFjM1JwWTJWaGJtUnFiM2x1WVhSc0xtOXladz09IiwiWVdOalpYTnpWRzlyWlc0PSI6Ik5USXlOV0V6TnpZeVlUWmhNamRqTldabFpEVmhOVEl6TjJRek4yTTNOemMzTjJZM04yUXpNMlExWmpRM05UUTFZVGMyWldVMFpqVmpOemMxTW1FM013PT0ifX0.WtiAgibdCQ2pp03Za-FJ2BlGRYy0wxd3vhxIiY-6mDE"
    }
  }
]

Information on your n8n setup

  • n8n version: 2.20.6
  • Database (default: SQLite): PostgresQL 15
  • n8n EXECUTIONS_PROCESS setting (default: own, main): Own
  • Running n8n via (Docker, npm, n8n cloud, desktop app): Docker on Digital Ocean.
  • Operating system: Ubuntu 24.04

@russellkg Olá! Se você está fazendo isso no seu servidor, como gerar o token, ou tem controle sobre o servidor https usado para gerar o token, você poderia fazer um código de autorização que a requisição precisa ter para acessar o token.

O que exatamente faz você achar que é inseguro, e onde você gostaria de melhorias?

bem vindo à comunidade n8n @russellkg

eu também protegeria onde os segredos ficam armazenados. O ideal é manter username/password em Credentials do n8n ou em um secrets manager, e não em Data Tables ou outputs de execução. Para vários clientes, o workflow pode receber um identificador do cliente e, a partir dele, usar a credencial correta para gerar ou renovar o token.

Estou passando uma ‘flag’ de cliente em vários lugares. Então implementei parte disso.

Principalmente, a razão pela qual fiz assim no começo é que precisava que algo funcionasse, e agora é hora de voltar e corrigir meu atalho para produtividade.

Como disse em meu post original, o bearer token que foi copiado para aquela mensagem é um exemplo. Ele expirou, e mesmo que não tivesse expirado, você precisaria descobrir qual cliente, qual tenant e quais credenciais são necessários com esse bearer token. De qualquer forma, neste ponto, ele retorna uma falha de autenticação. Não é possível autenticar ou renovar esse token. Além disso, este exercício é especificamente para tirar isso de meus fluxos de trabalho.

O que me leva ao próximo problema.

Uma vez que tenho o servidor retornando um bearer token para mim, onde coloco isso pelos 24 horas em que é válido? Não acredito que o nó bearer token possa ser editado por um fluxo de trabalho.

Parte do motivo pelo qual fiz isso assim foi porque não queria gerar um bearer token cada vez que me conectava, e não é óbvio o que devo fazer com o bearer.

Sei que terei mais perguntas.

Obrigado antecipadamente.

-Russ

@russellkg
Eu não tentaria gravar de volta em uma credencial Bearer Token do n8n. Essas credenciais são melhores para segredos estáveis, não para o seu caso.
Nesse caso, eu armazenaria o token em uma camada de cache/tabela com clientKey, accessToken e expiresAt, um Redis da vida, e criaria um workflow reutilizável “Get Valid Token”. Esse workflow verificaria se já existe um token válido para aquele cliente; se existir, retorna o token; se estiver expirado, gera um novo, atualiza o cache e retorna o novo valor.

Talvez isso ajude em parte disso.

Armazenamento em cache de token via arquivo é adequado - um arquivo json por cliente, nomeado com a chave do cliente, é um padrão limpo o suficiente e se escala bem.

O problema real é ter credenciais (email, senha, accessToken) vivendo no próprio workflow - dados de nó fixados aparecem no histórico de execução e qualquer pessoa com acesso ao workflow pode vê-los em texto simples no JSON do workflow.

** O fix que uso é ENV VARS. Carregue um arquivo .env na inicialização do n8n para que as credenciais nunca estejam no workflow. Escrevi como faço isso aqui:

Meu outro post:

Versão resumida - carregue um arquivo .env via script bat/shell na inicialização, defina N8N_BLOCK_ENV_ACCESS_IN_NODE=false, e depois faça referência como expressão, Variable Anchor como {{ $env.MOSYLE_EMAIL_CR }} etc. A UI lançará um aviso dizendo “não acessível”, mas se resolve bem em runtime. Por cliente, você simplesmente os agrupa em namespace: MOSYLE_EMAIL_CLIENT1, MOSYLE_EMAIL_CLIENT2 e assim por diante.

O nó HTTP Request usa parâmetros manuais de header/body para passar email, senha, accessToken — qualquer campo que aceite expressão, então env vars funcionam perfeitamente lá

Uma coisa só - env vars carregam apenas na inicialização, então não tente armazenar o próprio bearer token lá. Essa parte você já resolveu com o file write. A divisão é: credenciais estáticas (email/pass/accessToken) vão em .env, bearer token dinâmico fica no arquivo json. Nada sensível no workflow, e sua lógica de refresh de token existente continua funcionando exatamente como está.

Na verdade, verificar a data de expiração do campo de expiração do token não é uma forma muito confiável (o token pode ser revogado por outro motivo).

Uma abordagem melhor é:

  • Criar uma nova Credencial do tipo Bearer (ou credenciais do tipo Header se o campo tiver um nome personalizado) para cada token que você deseja usar.
  • Adicionar um fluxo de trabalho separado para verificar periodicamente se o token está ativo (por exemplo, fazer ping em algum endpoint/buscar dados básicos. Apenas para garantir que está ativo) para cada credencial. Ou adicionar um sub-fluxo com essa lógica de verificação para funcionar como um método proxy, que aceitará método http, url, query, body, nome da credencial/nome do token a usar, e chamar esse sub WF de cada pai que deve usar um token
  • Se o token não estiver ativo (expirado/inválido ou por outros motivos) >> chamar um endpoint /login para buscar um novo token e atualizar a credencial via HTTP Node e REST API do n8n patch /credentials/{id}

O método funciona bem se você não tiver muitos tokens; caso contrário, a abordagem com arquivo pode ser melhor.

E desative o Execution history para o fluxo de trabalho que gera um token. Assim

Ok. After much research and some AI added in, I’ve implemented a workflow. To highlight the parameters:

  • I have several clients using different tenants on the Mosyle platform.
  • n8n doesn’t (yet?) have a way to call credentials via an expression
  • Multiple workflows that do the same thing with different credentials is a recipe for nightmares

I’m using UpStash to store the credentials securely.

Here’s the workflow:

I think this is decent. It uses what @tamy.santos suggests. It doesn’t implement periodically checking the tokent as @barn4k suggested. That simply hasn’t been an issue. I’ll keep it under my hat in case it becomes and issue.

I also sanitized my workflows to verify I don’t have credentials laying around, waiting for anyone to happen along.