Já fiz exatamente isso antes. A recomendação de achamm sobre n8n-nodes-azure-openai-ms-oauth2 é a referência mais limpa se você estiver criando um nó customizado — gerencia o ciclo de vida completo do token no hook preSend do próprio nó e adiciona o parâmetro do corpo do recurso na atualização exatamente como você precisa. O código está no npm e GitHub, fácil de fazer fork.
Se você quer um template de starter ainda mais simples para consultar, o nó built-in do Google Drive do n8n tem lógica customizada de OAuth2 na definição de credencial que gerencia a atualização de token com parâmetros extras (está no repositório core do n8n em packages/nodes-base/credentials/GoogleOAuth2Api.credentials.ts). O padrão é quase idêntico: armazena tokens, verifica expiração, faz POST no endpoint de token com quaisquer campos de corpo extras que você precise, atualiza o token de acesso antes da requisição real sair.
Para seu caso específico — servidor OAuth customizado, precisa de recurso no corpo — a lógica de preSend seria mais ou menos assim (dentro do método execute ou preSend do seu nó customizado):
async preSend(request, options) {
const credentials = await this.getCredentials(‘myCustomOAuth2Api’);
// Verifica se o token expirou
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, // o parâmetro crucial do corpo
});
const tokenResponse = await this.helpers.httpRequest({
method: 'POST',
url: credentials.accessTokenUrl,
body: refreshParams.toString(),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
});
// Atualiza o cache de credenciais
credentials.accessToken = tokenResponse.access_token;
credentials.refreshToken = tokenResponse.refresh_token;
credentials.expiresAt = Date.now() + (tokenResponse.expires_in * 1000);
await this.setCredentials('myCustomOAuth2Api', credentials);
}
// Anexa token de acesso à requisição original
request.headers.Authorization = Bearer ${credentials.accessToken};
return request;
}
Esse é basicamente o esquema. Para produção, você adicionaria tratamento de erros e armazenamento de tokens apropriadamente (o objeto de credenciais do n8n persiste via banco de dados automaticamente).
Mas antes de escrever uma única linha de código — tente primeiro o truque do parâmetro de query. Apenas adicione ?resource=https://seu-alvo à sua accessTokenUrl. Se o servidor aceitar como parâmetro de query, você terminou em 10 segundos. Muitos servidores OAuth customizados aceitam, porque analisam ambos. Se for estritamente corpo apenas, então a rota de nó customizado é sólida e mantível a longo prazo.
Me avise qual caminho você acaba tomando — fico feliz em ajudar a debugar o hook preSend se você travar.