Generic Oauth2 wird nicht aktualisiert

Hallo zusammen,

Ich habe Schwierigkeiten, mich mit der API von Jobber zu integrieren. Ich habe mich anfangs authentifiziert und habe einige funktionsfähige Workflows, aber alles bricht nach 1 Stunde zusammen, wenn das access_token abläuft.

Jobber erfordert basierend auf meinen Tests keine speziellen Scopes, um das Refresh-Token zurückzugeben, aber aus irgendeinem Grund wird es entweder nicht zurückgegeben/gespeichert, oder n8n handhabt es auf andere Weise nicht richtig.

Hat jemand Vorschläge?

hier sind meine Troubleshooting-Informationen, die ich aus dem GitHub-Issue kopiert habe

Hier ist ihre Dokumentation - https://developer.getjobber.com/docs/building_your_app/app_authorization/

Ich kann mich anfangs autorisieren, aber nach der 1-Stunden-Gültigkeitsdauer erhalte ich den folgenden Fehler

Ausgabe
1 Element
Autorisierung fehlgeschlagen - bitte überprüfen Sie Ihre Anmeldedaten
Nicht unterstützter Content-Typ: text/plain; charset=utf-8
Fehlerdetails

Von HTTP Request
Fehlercode

401

Vollständige Meldung

Nicht unterstützter Content-Typ: text/plain; charset=utf-8
Anfrage

{ “hidden”: “{\n “query”: “{ quotes(first: 10, filter: { status: converted}) { nodes { id quoteNumber notes(first: 5) { nodes { … on QuoteNote { message } } } } } }”\n}”, “headers”: { “content-type”: “application/json”, “x-jobber-graphql-version”: “2025-04-16”, “accept”: “application/json,text/html,application/xhtml+xml,application/xml,text/;q=0.9, image/;q=0.8, /;q=0.7”, “Authorization”: “hidden” }, “method”: “POST”, “uri”: “https://api.getjobber.com/api/graphql”, “gzip”: true, “rejectUnauthorized”: true, “followRedirect”: true, “resolveWithFullResponse”: true, “sendCredentialsOnCrossOriginRedirect”: false, “followAllRedirects”: true, “timeout”: 300000, “encoding”: null, “json”: false, “useStream”: true }
Sonstige Informationen
Element-Index

0

Knotentyp

n8n-nodes-base.httpRequest

Knotenversion

4.4 (Neueste)

n8n-Version

2.20.6 (Self Hosted)

Zeit

5/12/2026, 9:52:03 AM

Stack Trace

NodeApiError: Authorization failed - please check your credentials at ExecuteContext.execute (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/n8n-nodes-base@file+packages+nodes-base_@aws-sdkaws-sdkaws-sdkaws-sdk+credential-providers@3.808.0_asn1.js@5_8da18263ca0574b0db58d4fefd8173ce/node_modules/n8n-nodes-base/nodes/HttpRequest/V3/HttpRequestV3.node.ts:825:16) at WorkflowExecute.executeNode (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/n8n-core@file+package@opent@openlemetry+core_@open@opentelemetrye@opentelemetryemetry+api@1.9.0_@opentelemetry+exporter-trace-otlp_2c2e1f47b69b34bef6f634a13cbf61d9/node_modules/n8n-core/src/execution-engine/workflow-execute.ts:1048:9) at WorkflowExecute.runNode (/usr/local/lib/@opentelemetrynpmode_modules/n8n/node_modules/.@opentelemet@opentelemetryynpm/n8n-co@opentelemetry@opentelemetry@file+packages+core_@opentelemetry+api@1.9.0_@opentelemetry+exporter-trace-otlp_2c2e1f47b69b34bef6f634a13cbf61d9/node_modules/n8n-core/@opentelemetryodulesrc/ex@opentelemetryode_modulescution-engine/workflow-execute.ts:1@opentelemetry39:11) at /@opentelemetrysr/local/lib/node_@opentelemetryodules/n8n/@opentelemetryode_modules/.pnpm/n8n-core@file+packages+core_@opentelemetry+api@@opentelemetry7.9.0_@opentelemetry+exporter-trace-otlp_2c2e1f47b69b34bef6f634a13cbf61d9/node_modules/n8n-core/s@opentelemetryc/execution@opentelemetryengine/workflow-execute.ts:1687:@opentelemetry7 at /usr/l@opentelemetrycal/lib/node_modules/n8n/node_modules/.pnpm/n8n-core@file+packages+core_@opentelemetry+api@1.9.0_@opentelemetry+exporter-trace-otlp_2c2e1f47b69b34bef6f634a13cbf61d9/node_modules/n8n-core/src/execution-engine/workflow-execute.ts:2339:11
Mein Verständnis ist, dass eine 401-Antwort einen Token-Refresh auslösen sollte, aber das scheint nicht zu geschehen. Das erneute Starten des Workflows hilft auch nicht.

Wenn ich in die Anmeldedaten gehe und auf “Reconnect” (Erneut verbinden) klicke, funktionieren nachfolgende Workflow-Ausführungen für eine Stunde.

So reproduzieren Sie den Fehler
Konfigurieren Sie Generic OAuth2-Anmeldedaten mit authorization_code für einen Provider, der Refresh-Tokens rotiert.
Workflow erfolgreich ausführen.
Warten Sie, bis das Access-Token abläuft.
Beobachten Sie den Refresh-Zyklus; nach dem nachfolgenden Zyklus schlägt die Authentifizierung fehl und erfordert eine erneute Verbindung.
Erwartetes Verhalten
n8n sollte die neuesten rotierten refresh_token aus der Token-Refresh-Antwort beibehalten und verwenden.
Workflows sollten ohne manuelle Reconnect-Aktion fortgesetzt werden.

Debug-Informationen
Debug-Informationen
core
n8nVersion: 2.20.6
platform: docker (self-hosted)
nodeJsVersion: 24.14.1
nodeEnv: production
database: sqlite
executionMode: regular
concurrency: -1
license: enterprise (production)
consumerId: 268c9581-f4d9-44ed-a7be-25c5c834d114
storage
success: all
error: all
progress: false
manual: true
binaryMode: filesystem
pruning
enabled: true
maxAge: 336 hours
maxCount: 10000 executions
client
userAgent: mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/148.0.0.0 safari/537.36
isTouchDevice: false
cluster
instanceCount: 1
versions: 2.20.6
instances:
instanceKey: 0cffc1ac-43d6-4469-85cf-116816732522, hostId: main-dec161f067e6, instanceType: main, instanceRole: leader, version: 2.20.6
checks:
check: hostid-clash, status: succeeded, warnings: -
check: lifecycle, status: succeeded, warnings: -
check: split-brain, status: succeeded, warnings: -
check: version-mismatch, status: succeeded, warnings: -
Generated at: 2026-05-12T17:00:18.159Z

Betriebssystem
Ubuntu 22.04 LTS

n8n-Version
2.20.6

Node.js-Version
whatever is in image: docker.n8n.io/n8nio/n8n

Datenbank
SQLite (Standard)

Ausführungsmodus
main (Standard)

Hosting
self hosted

Willkommen @oxidation0917 in unserer Community! Ich bin Jay und ich bin ein verifizierter n8n Creator.

Das ist ein bekannter Bug mit Generic OAuth2 - der Refresh Token wird in einigen Fällen nicht richtig gespeichert oder verwendet. Ein praktischer Workaround, während auf die Behebung gewartet wird: In den Generic OAuth2 Anmeldedaten stellst du sicher, dass “Authentication” auf “Body” eingestellt ist (nicht Header), falls Jobber das unterstützt, und überprüfst, dass die Token-URL korrekt ist und erforderliche Client-Anmeldedaten im Body enthält. Falls die Access Tokens von Jobber kurzlebig sind (1 Stunde), kannst du auch einen manuellen Refresh-Flow erstellen: einen geplanten Workflow, der alle 55 Minuten ausgeführt wird, ruft Jobbers Token-Endpunkt über HTTP Request mit grant_type: refresh_token auf und aktualisiert die Anmeldedaten über die n8n REST API. So bleibst du handlungsfähig, während der Bug behoben wird.

Hallo @nguyenthieutoan Vielen Dank, dass du dir das angeschaut hast.

Ich verwende derzeit Body in den Authentifizierungseinstellungen, da das die einzige Möglichkeit ist, wie es funktioniert. Wenn du sagst, dass ich überprüfen soll, ob Jobber die erforderlichen Anmeldedaten im Body enthält, meinst du damit, den Body eines curl-Befehls zu überprüfen?

Ich habe überlegt, den Ansatz zu verwenden, den du vorschlägst, mit einem Cron-Trigger, konnte mir das aber nicht ganz vorstellen und auch in der Dokumentation nicht so recht finden. Gibt es eine Möglichkeit, auf die gespeicherten Anmeldedaten (speziell refresh_token) in der HTTP-Anfrage zuzugreifen? Ich verstehe die Aktualisierung der Anmeldedaten über die API (ich muss mir da noch die Struktur überlegen), aber da die Anfrage den refresh_token benötigt, bin ich hängengeblieben, wie ich darauf zugreifen kann.

Hi @oxidation0917, ich helfe dir gerne, das ein wenig genauer zu erklären.

  1. Über “Anmeldedaten im Body”
    Als ich erwähnte, dass du überprüfen solltest, ob Jobber die erforderlichen Anmeldedaten im Body enthält, meinte ich: Vergleiche das, was du von n8n aus sendest, mit einem funktionierenden curl-Beispiel aus Jobbers Dokumentation oder aus deinen eigenen Tests. Zum Beispiel benötigt ein typischer OAuth2-Refresh-Aufruf im Body oft Felder wie:
  • grant_type=refresh_token

  • refresh_token=<dein_refresh_token>

  • client_id=<deine_client_id>

  • client_secret=<dein_client_secret>

Wenn dein curl-Beispiel funktioniert, aber der n8n HTTP Request Node fehlschlägt, kannst du den exakt gleichen Body und die Header aus dem curl in den Node übernehmen.

  1. Zugriff auf das gespeicherte refresh_token
    Leider macht n8n aufgrund des aktuellen Generic OAuth2 Bugs das gespeicherte refresh_token nicht einfach zugänglich innerhalb von regulären Nodes. Genau deshalb funktioniert das Auto-Refresh nicht. Anstatt also zu versuchen, das Refresh Token zur Laufzeit aus der Anmeldedatei zu “lesen”, ist der übliche Workaround:
  • Speichere das refresh_token an einem Ort, den du kontrollieren kannst, zum Beispiel in:

    • Einer n8n Variable (Umgebungsvariable), oder

    • Eine separate Datenbank/Tabelle, oder

    • Ein einfacher Datenspeicher wie PostgreSQL/Firestore/Notion, je nach deinem Stack.

  • Dann kann dein geplanter Workflow:

    • Das gespeicherte refresh_token auslesen

    • Jobbers Token-Endpoint mit grant_type=refresh_token aufrufen

    • Das Access Token in n8n über die REST API aktualisieren

  1. Skizze des manuellen Refresh-Flows
    Sehr grob gesagt würde der Workflow so aussehen:
  • Cron Node: läuft alle 55 Minuten

  • (Optional) Node zum Abrufen des neuesten gespeicherten refresh_token aus deinem Speicher

  • HTTP Request Node:

    • Methode: POST

    • URL: Jobbers Token-URL

    • Auth: keine (weil du alles im Body sendest)

    • Body: grant_type=refresh_token, refresh_token=..., client_id, client_secret, usw.

  • HTTP Request Node (n8n API):

    • Methode: PATCH

    • URL: https://<deine-n8n-url>/rest/credentials/<credential-id>

    • Auth: nutze deine n8n API Auth

    • Body: aktualisiere das accessToken (und optional das Refresh Token, falls Jobber ein neues zurückgibt)

Wenn du möchtest, kann ich dir ein konkretes JSON-Beispiel für sowohl die Jobber Token-Anfrage als auch die n8n Credential-Update-Payload zusammenstellen, damit du sie direkt in deine Instanz einfügen kannst.

Es sieht so aus, als würde n8n das refresh_token nach dem ersten OAuth-Flow nicht speichern. Ich würde die vollständige Token-Antwort von Jobber überprüfen und bestätigen, dass das Refresh-Token tatsächlich zurückgegeben und gespeichert wird. Manchmal geben Provider es nur bei der ersten Autorisierungsanfrage zurück.

Du könntest auch versuchen, Offline-Access- / Consent-Parameter in der OAuth-Konfiguration zu erzwingen. Da du bereits einen GitHub-Issue auf GitHub eröffnet hast, würde es wahrscheinlich helfen, die rohe Token-Antwort (mit gelöschten Secrets) zu teilen, um das Problem schnell einzugrenzen.

@nguyenthieutoan Danke! Das ist großartig. Ich bin gut auf dem Weg, schreibe eine Schritt-für-Schritt-Anleitung für die Nachwelt, stoße aber auf Probleme beim Update via API.

Zunächst habe ich versucht:

{
  "data": {
    "oauthTokenData": {
      "access_token": "access_token",
      "refresh_token": "refresh_token"
    }
  }
}

Aber ich bekomme

{
  "message": "request.body.data does not match allOf schema [subschema 0] with 12 error[s]:,request.body.data does not match allOf schema [subschema 0] with 1 error[s]:,request.body.data requires property \"grantType\",request.body.data does not match allOf schema [subschema 1] with 1 error[s]:,request.body.data requires property \"accessTokenUrl\",request.body.data does not match allOf schema [subschema 2] with 1 error[s]:,request.body.data requires property \"clientId\",request.body.data does not match allOf schema [subschema 3] with 1 error[s]:,request.body.data requires property \"clientSecret\",request.body.data does not match allOf schema [subschema 4] with 1 error[s]:,request.body.data requires property \"scope\",request.body.data does not match allOf schema [subschema 5] with 1 error[s]:,request.body.data requires property \"authentication\",request.body.data does not match allOf schema [subschema 1] with 2 error[s]:,request.body.data does not match allOf schema [subschema 0] with 1 error[s]:,request.body.data requires property \"serverUrl\",request.body.data does not match allOf schema [subschema 2] with 4 error[s]:,request.body.data does not match allOf schema [subschema 0] with 1 error[s]:,request.body.data requires property \"authUrl\",request.body.data does not match allOf schema [subschema 1] with 1 error[s]:,request.body.data requires property \"authQueryParameters\",request.body.data does not match allOf schema [subschema 3] with 4 error[s]:,request.body.data does not match allOf schema [subschema 0] with 1 error[s]:,request.body.data requires property \"sendAdditionalBodyProperties\",request.body.data does not match allOf schema [subschema 1] with 1 error[s]:,request.body.data requires property \"additionalBodyProperties\",request.body.data does not match allOf schema [subschema 4] with 2 error[s]:,request.body.data does not match allOf schema [subschema 0] with 1 error[s]:,request.body.data requires property \"jwksUriNotice\""
}

Ich habe versucht, es zu geben, und nach einigen Iterationen mit Claude bin ich am Ende bei folgendem:

{
  "data": {
    "grantType": "authorizationCode",
    "clientId": "clientId",
    "clientSecret": "clientSecret",
    "accessTokenUrl": "https://api.getjobber.com/api/oauth/token",
    "authUrl": "https://api.getjobber.com/api/oauth/authorize",
    "serverUrl": "{{MY N8N HOST?}}"
    "authQueryParameters": "",
    "scope": "",
    "authentication": "body",
    "jweEnabled": false,
    "oauthTokenData": {
      "access_token": "access_token",
      "refresh_token": "refresh_token",
      "token_type": "Bearer"
    }
  }
}

was die Schema-Überprüfungen zu bestehen scheint, aber jetzt bekomme ich einen 500-Fehler. Ich weiß nicht, was in serverURL stehen sollte, also habe ich meinen n8n-Host eingegeben.

Code	Details
500
Undocumented
Error: Internal Server Error

Response body
Download




Error




Internal Server Error



Das ist meine Anmeldedaten-Struktur aus der Datenbank, die keine der zusätzlichen Parameter enthält, die die API verlangt. @David_Warner, es sieht so aus, als würde n8n refresh_token speichern.

{
    "authUrl": "https://api.getjobber.com/api/oauth/authorize",
    "accessTokenUrl": "https://api.getjobber.com/api/oauth/token",
    "clientId": "clientId",
    "clientSecret": "clientSecret",
    "scope": "offline_access",
    "authentication": "body",
    "oauthTokenData": {
        "access_token": "access_token",
        "refresh_token": "refresh_token",
        "token_type": "Bearer"
    }
}

Moment mal. Ich habe die API-Aktualisierung zum Laufen gebracht, nachdem ich mit dem Request_Body herumgespielt habe. Ich werde bald Details teilen.

Edit - Hier ist das, was ich bisher dokumentiert habe.

Ein großes Dankeschön an @nguyenthieutoan, dass er mich in die richtige Richtung gewiesen hat. Ich habe große Fortschritte gemacht.

In der Hoffnung, dies für jemand anderen (und auch für mich selbst) in Zukunft einfacher zu gestalten, bin ich alle Auth-Schritte erneut durchgegangen und habe dabei dokumentiert.

Initiale Authentifizierung / Tests

  1. Autorisierungs-URL - Geben Sie sie in einen Browser ein, der mit Jobber authentifiziert ist. Die URL, zu der Sie weitergeleitet werden, enthält den Autorisierungscode und den Status als Bestätigung.
https://api.getjobber.com/api/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=https:/YOUR_HOST/rest/oauth2-credential/callback&state=abc123

Antwort, die ich erhalten habe:

https://n8n.lab.atreehuman.com/rest/oauth2-credential/callback?code=CODE&state=abc123
  1. Curl mit Autorisierungscode - Passen Sie diesen CURL mit Ihrem code aus der vorherigen URL an
curl -X POST https://api.getjobber.com/api/oauth/token -H "Content-Type: application/x-www-form-urlencoded" -d "client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=authorization_code&code=CODE&redirect_uri=YOUR_HOST/rest/oauth2-credential/callback"

Antwort:

{"access_token":"ACCESS_TOKEN","refresh_token":"REFRESH_TOKEN"}%

Sie sind jetzt authentifiziert und haben 1 Stunde Zeit, um Ihren access_token zu aktualisieren, bevor er abläuft. Ihr refresh_token sollte danach funktionieren (unbegrenzt bis zur Rotation?). Standardmäßig rotiert die Jobber-API den refresh_token bei jeder Aktualisierung Ihres access_token. Sie müssen Ihren refresh_token an einem Ort speichern, auf den aus einem Workflow zugegriffen werden kann.

  1. Testen Sie die API-Authentifizierung:
curl -X POST -H "Authorization: Bearer ACCESS_TOKEN" "https://api.getjobber.com/api/graphql"

Antwort bei Authentifizierung:

{"message":"An API version must be specified"}%

n8n-Anmeldedaten aktualisieren

  1. Erstellen Sie einen API-Schlüssel unter Einstellungen > n8n API mit den Bereichen credential:list, credential_update und credential:read. Speichern Sie den nach beiden in der Popup angezeigten Schlüssel in Ihre Zwischenablage und an einem sicheren Ort. Sie benötigen ihn später beim Erstellen des Cron-Workflows zur Aktualisierung.

  2. Öffnen Sie den API Playground und authentifizieren Sie sich mit Ihrem API-Schlüssel. Ich musste die Seite nach der Authentifizierung aktualisieren, damit die Authentifizierung in Kraft tritt.

  3. Scrollen Sie nach unten zu GET /credentials klicken Sie auf “Try it out”

  4. Finden Sie Ihre Jobber-Anmeldedaten in den Antwortdaten und speichern Sie die id in Ihren Editor und Ihre Zwischenablage

  5. Scrollen Sie weiter nach unten und finden Sie PATCH /credentials/id, klicken Sie auf “Try it out” und fügen Sie Ihre id ein.

  6. Fügen Sie in “Request Body” das Folgende ein und aktualisieren Sie es mit Ihren Daten. (refresh_token muss hier nicht wirklich sein, da n8n es nicht verwendet)

{
    "data": {
        "grantType": "authorizationCode",
        "serverUrl": "",
        "jweEnabled": false,
        "clientId": "CLIENT_ID",
        "clientSecret": "CLIENT_SECRET",
        "accessTokenUrl": "https://api.getjobber.com/api/oauth/token",
        "authUrl": "https://api.getjobber.com/api/oauth/authorize",
        "scope": "",
        "authentication": "body",
        "authQueryParameters": "",
        "oauthTokenData": {
            "access_token": "ACCESS_TOKEN",
            "refresh_token": "REFRESH_TOKEN"
        }
    }
}

Sie sollten einen Code 200 mit dem Antworttext erhalten:

{
    "id": "ID",
    "name": "Jobber",
    "type": "oAuth2Api",
    "isManaged": false,
    "isGlobal": false,
    "isResolvable": false,
    "resolvableAllowFallback": false,
    "resolverId": null,
    "createdAt": "2026-05-09T17:53:07.738Z",
    "updatedAt": "2026-05-16T19:27:53.231Z"
}

Nun bleibt nur noch, Ihren refresh_token an einem sicheren Ort zu speichern, auf den aus einem Workflow zugegriffen werden kann, und dann einen Workflow zu erstellen, der den Token aktualisiert und die API aktualisiert.

Ihren access_token aktualisieren

curl -X POST https://api.getjobber.com/api/oauth/token -H "Content-Type: application/x-www-form-urlencoded" -d "client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=refresh_token&refresh_token=REFRESH_TOKEN"

Antwort:

{"access_token":"ACCESS_TOKEN","refresh_token":"REFRESH_TOKEN"}%

Nehmen Sie das einfach und aktualisieren Sie Ihre Anmeldedaten wie oben mit der API, und Sie sollten bereit sein. Jetzt muss all dies nur noch in einen Workflow umgewandelt werden und ein Notfall-Patch angebracht werden!

So, I’m still hoping to get this issue resolved, but for now we can workaround it.

Here’s a workflow I came up with. You’d have to set up a Postgres database / credentials and point those nodes at it as well as set an error reporting workflow, or disable that flag.

I don’t really like storing the credentials in the database, but currently it’s the most practical approach without a self-hosted enterprise license. Any suggestions otherwise that are more secure?

I’m open to any suggestions on the workflow too. Thanks all!

Bearbeitung - Nicht mehr als Lösung gekennzeichnet.

Naja, es ist irgendwie eine Lösung. Sie lässt die Authentifizierung länger anhalten. Vielleicht einen Tag lang, aber es scheint, dass n8n doch das Token aktualisiert, nur nach seinem eigenen Zeitplan. Das führt am Ende dazu, dass es das Provisorium zerstört.

Ist es möglich, dass dies auch GitHub OAuth2 API-Anmeldedaten betrifft, nicht nur generische OAuth2-Anmeldedaten? Ich verwende GitHub OAuth2-Anmeldedaten zusammen mit GitHub-Knoten, um Informationen abzurufen. Ich erhalte seit kurzem einen 401-Fehler:
{ "message": "Bad credentials", "documentation_url": "https://docs.github.com/rest", "status": "401" }

Ich kann dies manuell beheben, indem ich auf der Anmeldedatenseite auf die Schaltfläche „Erneut verbinden

Ich habe das gleiche Problem mit einem MCP-OAuth2-API-Node. Er aktualisiert das Token nicht. Gibt es Updates zur Behebung des Problems?

Zwei Dinge sollten überprüft werden, die oft übersehen werden: Erstens, stelle sicher, dass das Feld „Refresh URL

Danke für die Antwort, @nguyenthieutoan. Ja, ich habe beide bereits ausprobiert, aber es wird nach etwa 1 Stunde nicht aktualisiert.

Bei der URL habe ich ja beide ausgefüllt, Auth URL und Access Token URL.

Gibt es noch andere Tipps zur Fehlerbehebung?

Danke!

Bei Google wird das Refresh-Token nur einmal ausgegeben – bei der allerersten Autorisierung. Wenn du ohne access_type=offline und prompt=consent im Feld „Auth URI Query Parameters

Danke, das scheint funktioniert zu haben.

Ich wusste nicht, wie man beides sendet, aber es war einfach: "access_type=offline&prompt=consent"