Ich habe das schon genau so gemacht. achamm’s Empfehlung von n8n-nodes-azure-openai-ms-oauth2 ist die sauberste Referenz, wenn du einen Custom Node baust — es verwaltet den gesamten Token-Lebenszyklus im preSend Hook des Nodes und fügt den Resource-Body-Parameter bei der Aktualisierung genau so hinzu, wie du es brauchst. Der Source ist auf npm und GitHub, leicht zu forken.
Wenn du eine noch einfachere Starter-Template sehen möchtest, hat der eingebaute n8n Google Drive Node eine Custom-OAuth2-Logik in seiner Credential-Definition, die Token-Refresh mit zusätzlichen Parametern verwaltet (sie ist im n8n Core Repo unter packages/nodes-base/credentials/GoogleOAuth2Api.credentials.ts). Das Muster ist fast identisch: Tokens speichern, Ablauf prüfen, zum Token-Endpoint mit den zusätzlichen Body-Feldern POSTen, die Access-Token aktualisieren, bevor die eigentliche Anfrage rausgeht.
Für deinen spezifischen Fall — Custom OAuth Server, brauche Resource im Body — würde die preSend-Logik ungefähr so aussehen (in der execute oder preSend Methode deines Custom Nodes):
async preSend(request, options) {
const credentials = await this.getCredentials(‘myCustomOAuth2Api’);
// Check if token is expired
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, // the crucial body param
});
const tokenResponse = await this.helpers.httpRequest({
method: 'POST',
url: credentials.accessTokenUrl,
body: refreshParams.toString(),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
});
// Update credentials cache
credentials.accessToken = tokenResponse.access_token;
credentials.refreshToken = tokenResponse.refresh_token;
credentials.expiresAt = Date.now() + (tokenResponse.expires_in * 1000);
await this.setCredentials('myCustomOAuth2Api', credentials);
}
// Attach access token to original request
request.headers.Authorization = Bearer ${credentials.accessToken};
return request;
}
Das ist im Grunde der Blueprint. Für Production würdest du Error Handling hinzufügen und Token Speicherung ordnungsgemäß durchführen (n8n’s Credentials-Objekt persistiert automatisch über die Datenbank).
Aber bevor du eine einzige Zeile Code schreibst — versuch zuerst den Query-Parameter-Trick. Hänge einfach ?resource=https://your-target an deine accessTokenUrl an. Wenn der Server das als Query-Parameter akzeptiert, bist du in 10 Sekunden fertig. Viele Custom OAuth Server tun das, weil sie beides parsen. Falls es streng Body-only ist, ist die Custom-Node-Route solid und langfristig wartbar.
Sag mir Bescheid, welchen Weg du am Ende gehst — ich helfe gerne beim Debuggen des preSend Hooks, wenn du steckenbleibst.