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.
@russellkg Bonjour ! Si tu fais ça sur ton serveur, par exemple en générant le token, ou si tu contrôles le serveur https utilisé pour générer le token, tu pourrais créer un code d’autorisation que la requête doit avoir pour accéder au token.
Qu’est-ce qui te fait penser exactement que c’est non sécurisé, et où aimerais-tu des améliorations ?
je protégerais aussi l’endroit où les secrets sont stockés. L’idéal est de conserver les identifiants/mots de passe dans les Credentials de n8n ou dans un gestionnaire de secrets, et non dans les Data Tables ou les outputs d’exécution. Pour plusieurs clients, le workflow peut recevoir un identifiant client et, à partir de celui-ci, utiliser les bonnes informations d’identification pour générer ou renouveler le token.
Je passe un ‘flag’ client à différents endroits. J’ai donc implémenté une partie de ça.
La principale raison pour laquelle j’ai procédé de cette façon au départ, c’est que j’avais besoin d’avoir quelque chose de fonctionnel, et maintenant c’est le moment de revenir en arrière et de corriger mon raccourci vers la productivité.
Comme je l’ai dit dans mon message initial, le bearer token qui a été copié dans ce message est un exemple. Il a expiré, et même s’il ne l’était pas, tu devrais déterminer quel client, quel tenant et quelles credentials sont nécessaires avec ce bearer token. De toute façon, à ce stade, il retourne une authentification échouée. Il n’est pas possible d’authentifier ou de renouveler ce token. De plus, cet exercice vise précisément à éliminer cela de mes workflows.
Ce qui m’amène au prochain casse-tête.
Une fois que j’aurai le serveur qui me retourne un bearer token, où le mettre pendant les 24 heures où il est valide ? Je ne crois pas que le nœud bearer token puisse être modifié par un workflow.
La raison pour laquelle j’ai procédé de cette façon était que je ne voulais pas générer un bearer token à chaque connexion, et il n’est pas évident de savoir ce que je suis censé faire avec le bearer.
@russellkg
Je ne tenterais pas de réécrire dans une credential Bearer Token de n8n. Ces credentials sont mieux adaptées aux secrets stables, pas à votre cas.
Dans ce cas, je stockerais le token dans une couche cache/table avec clientKey, accessToken et expiresAt, un Redis du genre, et je créerais un workflow réutilisable « Get Valid Token ». Ce workflow vérifierait s’il existe déjà un token valide pour ce client ; s’il existe, il retourne le token ; s’il est expiré, il génère un nouveau, met à jour le cache et retourne la nouvelle valeur.
La mise en cache des jetons via fichier est correcte - un fichier JSON par client, nommé avec la clé du client, est un modèle assez propre et il s’adapte bien.
Le vrai problème est que les credentials (email, mot de passe, accessToken) se trouvent dans le workflow lui-même - les données du nœud épinglé s’affichent dans l’historique d’exécution et n’importe qui ayant accès au workflow peut les voir en texte brut dans le JSON du workflow.
**La solution que j’utilise, ce sont les VARIABLES D’ENVIRONNEMENT. Charger un fichier .env au démarrage de n8n pour que les credentials ne soient jamais dans le workflow du tout. J’ai écrit comment je le fais ici :
Mon autre post :
Version courte - charger un fichier .env via un script bat/shell au démarrage, définir N8N_BLOCK_ENV_ACCESS_IN_NODE=false, puis référencer comme expression, Variable Anchor du genre {{ $env.MOSYLE_EMAIL_CR }} etc. L’interface affichera un avertissement disant « non accessible » mais ça fonctionne bien à l’exécution. Par client, tu les mets simplement en namespace : MOSYLE_EMAIL_CLIENT1, MOSYLE_EMAIL_CLIENT2 et ainsi de suite.
Le nœud HTTP Request utilise les paramètres manuels d’en-tête/corps pour passer l’email, le mot de passe, l’accessToken — n’importe quel champ acceptant une expression, donc les variables d’environnement fonctionnent parfaitement là
Une chose cependant - les variables d’environnement ne se chargent qu’au démarrage, donc n’essaie pas d’y stocker le bearer token lui-même. Tu as déjà résolu cette partie avec l’écriture de fichier. La séparation est : les credentials statiques (email/pass/accessToken) vont dans .env, le bearer token dynamique reste dans le fichier JSON. Rien de sensible dans le workflow, et ta logique de rafraîchissement des jetons existante fonctionne exactement comme avant.
En fait, vérifier la date d’expiration à partir du champ d’expiration du jeton n’est pas une méthode très fiable (le jeton peut être révoqué pour une autre raison).
Une meilleure approche :
Créer une nouvelle Credential de type Bearer (ou des credentials de type Header si le champ a un nom personnalisé) pour chaque jeton que vous souhaitez utiliser.
Ajouter un workflow séparé pour vérifier périodiquement si le jeton est actif (par exemple, envoyer un ping à un endpoint/récupérer des données de base. Juste pour s’assurer qu’il est actif) pour chaque credential. Ou ajouter un sous-workflow avec cette logique de vérification pour fonctionner comme une méthode proxy, qui acceptera la méthode http, l’url, la requête, le corps, le nom de la credential/nom du jeton à utiliser, et appeler ce sous-WF à partir de chaque parent qui devrait utiliser un jeton
Si le jeton n’est pas actif (expiré/invalide ou pour d’autres raisons) >> appeler un endpoint /login pour récupérer un nouveau jeton et mettre à jour la credential via le nœud HTTP et l’API REST de n8n patch /credentials/{id}
Cette méthode fonctionne bien si vous n’avez pas beaucoup de jetons ; sinon, l’approche par fichier peut être meilleure.
Et désactiver l’historique d’exécution pour le workflow qui génère un jeton. Comme ceci
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.