Paramètres du corps pour la demande de refresh token dans le flux OAuth

Je essaie de me connecter à une API externe en utilisant le flux OAuth avec l’approche des fichiers d’identifiants pour un nœud personnalisé. Le problème que j’ai est que, pour le serveur OAuth lors du renouvellement du jeton, je dois envoyer le paramètre resource comme paramètre de corps pour récupérer un jeton d’accès correctement renouvelé.

Y a-t-il quelqu’un qui a géré ce genre de scénario ? Les paramètres de corps standard ne suffisent pas.

@shamika l’helper de credentials OAuth2 standard dans n8n n’expose pas la customization de refresh-body directement, mais il y a plusieurs approches selon le serveur que tu cibles.

si c’est spécifiquement Microsoft/Azure AD (cas le plus courant pour avoir besoin du paramètre resource body), la correction la plus propre à long terme est de passer des endpoints v1.0 à v2.0 — Microsoft a déprécié le paramètre resource il y a des années et l’a remplacé par scope-with-resource-baked-in. au lieu de body resource=https://graph.microsoft.com, ton scope devient https://graph.microsoft.com/.default. l’endpoint v2.0 est /oauth2/v2.0/token au lieu de /oauth2/token. zéro code custom nécessaire si tu peux changer les endpoints.

si tu ne peux pas changer les endpoints (certains serveurs OAuth legacy/enterprise requièrent vraiment resource en body), le chemin pour un nœud custom est de NE PAS étendre oAuth2Api et à la place de définir ton propre type de credential avec IAuthenticateGeneric et gérer le refresh manuellement:

{
  "name": "myCustomOAuth2Api",
  "displayName": "My Custom OAuth2",
  "properties": [
    {"displayName": "Client ID", "name": "clientId", "type": "string"},
    {"displayName": "Client Secret", "name": "clientSecret", "type": "string", "typeOptions": {"password": true}},
    {"displayName": "Resource", "name": "resource", "type": "string"}
  ],
  "authenticate": {
    "type": "generic",
    "properties": {
      "headers": {"Authorization": "=Bearer {{ $credentials.accessToken }}"}
    }
  }
}

ensuite dans le nœud implémente le refresh du token manuellement via le hook preSend en vérifiant l’expiry et en POSTant vers l’URL de token avec tes paramètres body requis (incluant resource). ça ajoute de la complexité mais te donne le contrôle total du flux de refresh.

troisième option si tu veux continuer à étendre oAuth2Api et tu as juste besoin de resource attaché — essaie de l’ajouter comme query param sur accessTokenUrl lui-même, le flux standard de n8n passe aussi les query params lors de la demande de refresh. par ex accessTokenUrl: https://login.example.com/token?resource=https://api.example.com. moins propre mais le patch minimal.

quel serveur OAuth tu connectes? Azure AD, Salesforce, Ping Identity, une custom enterprise? ça change quelle approche est la plus réaliste.

@achamm a bien couvert les chemins principaux. Un ajout pratique : avant de prendre la route IAuthenticateGeneric, confirmez d’abord quel serveur OAuth vous ciblez. S’il s’agit d’un serveur moderne (Azure AD, Google, Okta), le point de terminaison v2 basé sur scope est presque toujours le bon choix et ne nécessite aucun code personnalisé. S’il s’agit d’un serveur OAuth hérité ou sur site qui nécessite réellement resource comme paramètre de corps - c’est là que IAuthenticateGeneric + le hook preSend manuel est la solution la plus propre. Pouvez-vous partager quel service/serveur OAuth vous connectez ? Cela nous aidera à réduire le bon chemin.

Bonjour @achamm, merci pour la réponse détaillée. Le serveur OAuth est un serveur personnalisé auto-hébergé d’un client. Pour le contexte, le jeton d’accès est un JWT, donc lors du renouvellement, comme aucune ressource n’est spécifiée, j’ai reçu un jeton opaque au lieu d’un JWT. Mais dans l’échange de code initial, puisque les paramètres du corps peuvent être envoyés via « sendAdditionalBodyProperties », j’ai obtenu un JWT.

J’ai utilisé Postman pour obtenir manuellement un jeton de renouvellement avec le paramètre resource dans le corps, et j’ai obtenu un JWT parfait, ce qui confirme que le paramètre resource fait la différence.

Un jeton opaque n’est pas acceptable puisque le service à développer sera sans serveur et l’authentification doit être autonome. Je préférerais une solution propre ici car je dois la maintenir pour le client.

Deux options que j’envisage sont l’option de paramètre de requête, mais je ne sais toujours pas si le serveur la respecte. L’autre est la logique de renouvellement personnalisée. Avez-vous vu un nœud qui a implémenté ce type de mécanisme de jeton de renouvellement personnalisé à titre de référence ?

@shamika la référence existante la plus propre est le nœud communautaire n8n-nodes-azure-openai-ms-oauth2 sur npm — il implémente exactement ce modèle (actualisation OAuth MS personnalisée avec paramètre de corps de ressource) en N’étendant PAS oAuth2Api et en gérant plutôt le cycle de vie du jeton dans le hook preSend du nœud. pour ton flux custom-server c’est à peu près ~50 lignes de TypeScript : stocke accessToken/refreshToken/expiresAt dans la credential, vérifie l’expiration dans preSend, POST vers ton endpoint token avec le corps de ressource quand expiré, mets à jour le token en cache avant de transférer la requête réelle.

ça vaut le coup d’essayer d’abord la route avec paramètre de requête puisque c’est zéro code — le flux OAuth2Api standard de n8n transmet effectivement les paramètres de requête URL à la demande d’actualisation, donc si tu définis accessTokenUrl sur https://ur-server/token?resource=https://api.target.com et que ton serveur OAuth accepte resource du corps ou de la requête, ça marche tout simplement sans forker quoi que ce soit. ça dépend entièrement de si ton serveur est strict body-only.

si c’est strict body-only, la source de n8n-nodes-azure-openai-ms-oauth2 est le blueprint — forke-la, remplace les endpoints/scopes spécifiques à MS par ceux de ton serveur, livre-la comme nœud communautaire privé. bien plus propre à long terme qu’un hack de nœud Code.

bienvenue dans la communauté n8n @shamika
peux-tu s’il te plaît partager ton JSON sans les données sensibles ?

J’ai déjà fait exactement la même chose. La recommandation d’achamm sur n8n-nodes-azure-openai-ms-oauth2 est la référence la plus propre si tu construis un nœud personnalisé — elle gère l’intégralité du cycle de vie des jetons dans le hook preSend du nœud et ajoute le paramètre du corps de la ressource au moment du rafraîchissement exactement comme tu en as besoin. Le code source est sur npm et GitHub, facile à forker.

Si tu veux un modèle de démarrage encore plus simple à consulter, le nœud Google Drive intégré de n8n a une logique OAuth2 personnalisée dans sa définition de credential qui gère le rafraîchissement des jetons avec des paramètres supplémentaires (c’est dans le dépôt n8n core sous packages/nodes-base/credentials/GoogleOAuth2Api.credentials.ts). Le schéma est pratiquement identique : stocker les jetons, vérifier l’expiration, POSTer vers le point de terminaison des jetons avec les champs de corps supplémentaires dont tu as besoin, mettre à jour le jeton d’accès avant que la vraie requête ne soit envoyée.

Pour ton cas spécifique — serveur OAuth personnalisé, besoin de ressource dans le corps — la logique preSend ressemblerait à quelque chose comme ça (à l’intérieur de la méthode execute ou preSend de ton nœud personnalisé) :

async preSend(request, options) {

const credentials = await this.getCredentials(‘myCustomOAuth2Api’);

// Vérifier si le jeton est expiré

if (Date.now() > credentials.expiresAt) {

const refreshParams = new URLSearchParams({

  grant_type: 'refresh_token',

  refresh_token: credentials.refreshToken,

  client_id: credentials.clientId,

  client_secret: credentials.clientSecret,

  resource: credentials.resource, // le paramètre de corps crucial

});

const tokenResponse = await this.helpers.httpRequest({

  method: 'POST',

  url: credentials.accessTokenUrl,

  body: refreshParams.toString(),

  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },

});

// Mettre à jour le cache des credentials

credentials.accessToken = tokenResponse.access_token;

credentials.refreshToken = tokenResponse.refresh_token;

credentials.expiresAt = Date.now() + (tokenResponse.expires_in * 1000);

await this.setCredentials('myCustomOAuth2Api', credentials);

}

// Joindre le jeton d’accès à la requête originale

request.headers.Authorization = Bearer ${credentials.accessToken};

return request;

}

C’est essentiellement le plan directeur. Pour la production, tu ajouterais une gestion des erreurs et un stockage des jetons approprié (l’objet credentials de n8n persiste via la base de données automatiquement).

Mais avant que tu écrives une seule ligne de code — essaye d’abord l’astuce du paramètre de requête. Ajoute simplement ?resource=https://your-target à ton accessTokenUrl. Si le serveur l’accepte comme paramètre de requête, c’est réglé en 10 secondes. Beaucoup de serveurs OAuth personnalisés le font, parce qu’ils analysent les deux. Si c’est strict et corps uniquement, alors la route du nœud personnalisé est solide et maintenable à long terme.

Fais-moi savoir quel chemin tu finis par emprunter — je serais ravi de t’aider à déboguer le hook preSend si tu te trouves bloqué.

Bonjour, voici une mise à jour pour ceux qui consulteraient ce sujet. Comme le serveur d’authentification était personnalisé, nous avons pu injecter le paramètre resource dans le corps du point de terminaison de jeton à partir d’un proxy de confiance. Nous n’avons donc apporté aucune modification au flux par défaut de n8n.

Salut merci pour ta réponse, j’ai fait une réponse de mise à jour sur le cas que j’ai ajouté. On a réussi à résoudre ça avec une approche de proxy de confiance plutôt qu’un flux de credential n8n personnalisé. Je pense que cette approche est plus propre et meilleure en termes de maintenabilité.