Open API Token-Lebenszyklus
Die cTrader Open API erlaubt ein gültiges Access-Token pro cTrader-ID (cID) gleichzeitig. Sobald ein neues Token ausgestellt wird – eine geplante Aktualisierung oder eine erneute Autorisierung, wenn der Benutzer ein weiteres Konto derselben cID verknüpft – wird das vorherige Access-Token ungültig. Eine Copy-Engine, die auf einem Remote-Node läuft, hält dieses nun tote Token, weshalb das neue Token es erreichen muss, ohne die Live-Verbindung zu kappen.
Modell
OpenApiAuthorizationist das Aggregate, das die verschlüsselten Access- und Refresh-Tokens einer cID hält. Ein eindeutiger Index auf(UserId, CtidUserId)erzwingt genau eine Autorisierung pro cID pro Benutzer.TokenVersion— ein monotoner Zähler, der bei jeder Token-Rotation erhöht wird (Refresh(), deckt auch den Re-Auth-Pfad ab, wenn ein weiteres Konto derselben cID verknüpft wird). Er ist der Versionsmarker für die Einzel-gültiges-Token-Regel und das, was ein laufender Host verwendet, um eine Änderung zu erkennen, selbst wenn zwei Token-Strings zufällig kollidieren.- Tokens werden im Ruhezustand über
ISecretProtectorverschlüsselt (EncryptionPurposes.OpenApiAccessToken/OpenApiRefreshToken). Sie werden niemals im Klartext protokolliert oder gespeichert.
Weitergabe (sanfter In-Place-Tausch)
- Ein Token wird rotiert → das neue Token + erhöhte
TokenVersionwerden gespeichert. - Der
CopyEngineSupervisorauf dem Hosting-Node liest den Plan in jedem Abgleichzyklus neu und berechnet eine Token-Signatur (Access-Tokens + Versionen). Eine Änderung bedeutet eine Rotation. - Anstatt den Host abzubauen und neu zu starten (was den Master-Ausführungsstream kappen würde), pusht der Supervisor das neue Token zum laufenden Host.
- Der Host authentifiziert das betroffene Konto auf dem bestehenden Socket erneut
(
ProtoOAAccountAuthReqerneut) überSwapAccessTokenAsync, dann findet ein kurzer Abgleich statt. Das alte Token stirbt; der Copy-Stream hört nie auf.
Das macht den Fall über cIDs hinweg sicher: Ein Benutzer, der mitten im Betrieb ein zweites Konto derselben cID hinzufügt, macht das alte Token ungültig, und das laufende Copy-Profil läuft mit dem neuen weiter.
Aktualisierung
OpenApiTokenRefreshService (Hintergrunddienst) aktualisiert proaktiv Autorisierungen vor Ablauf;
OpenApiAuthorization.IsExpiring(threshold, now) steuert dies. cTrader rotiert das
Refresh-Token bei jeder Aktualisierung, also wird das neue Refresh-Token sofort gespeichert; ein
schreibgeschützter Cache, der nicht persistieren kann, macht sich selbst ungültig (relevant für den
In-Cluster-Test-Job, der eine beschreibbare Kopie des Secrets einhängt).
Failure-Escalation
Eine fehlgeschlagene Aktualisierung ist nicht still. OpenApiAuthorization.MarkRefreshFailed(reason, now, criticalWindow)
speichert RefreshFailedAt, erhöht ConsecutiveRefreshFailures und löst immer ein
AccessTokenRefreshFailed (Warning) aus. Wenn das Token nun innerhalb von
App:OpenApi:TokenRefreshCriticalWindow (Standard 6h) vor Ablauf liegt und die Aktualisierung weiterhin
fehlschlägt, eskaliert es einmalig mit einem AccessTokenRefreshCritical Domain Event + Critical-Log,
sodass der Eigentümer die Autorisierung erneuern kann, bevor Copy/Prop-Firm-Operationen das Token
verlieren. Der Fehlerzähler und die Eskalations-Sperre werden beim nächsten erfolgreichen Refresh
zurückgesetzt. Der Dienst versucht es weiterhin alle TokenRefreshInterval, sodass ein
Provider-/Wartungsausfall sich selbst heilt, wenn der Refresh-Endpunkt zurückkehrt.
Invalidierungs-Alert & Auto-Recovery (M1)
Eine Teil-/Wieder-Autorisierung auf einer cID macht das Token ungültig, das ein laufender Copy-Host noch
hält. Wenn ein Trading-Aufruf mit OpenApiErrorKind.TokenInvalid abgelehnt wird, löst der Host einen
eigenständigen CopyTokenInvalidated-Alert aus (Log 1078) — kein generischer Fehler — damit der
Benachrichtigungskanal weiß, dass ein Token Aufmerksamkeit erfordert. Die Recovery ist automatisch: Der
Supervisor liest die Autorisierung in jedem Zyklus neu, und wenn das aktualisierte Token die
Token-Signatur ändert, pusht er es in den laufenden Host für einen In-Place-Tausch — das Kopieren
wird ohne manuelles erneutes Hinzufügen fortgesetzt. Ein NotLinkable-Profil (Token/Auth vorübergehend
nicht auflösbar) wird ebenfalls in jedem Supervisor-Zyklus neu ausgewertet und gehostet, sobald sein Plan
wieder aufgebaut wird.
Host-Liveness-Watchdog (M2)
Der Supervisor überwacht die Run-Task jedes gehosteten Profils. Wenn ein Host beendet wird oder einen
Fehler hat, während sein Profil noch diesem Node zugewiesen ist, bricht der Watchdog ab und
startet ihn im nächsten Zyklus neu (Log CopyHostRestarted), sodass ein festgefahrener Host sich
selbst heilt, anstatt einen manuellen Neustart zu benötigen — und das Scheitern eines Profils nie die
anderen blockiert (Per-Profil-Isolation).
Tests
- Unit —
TokenVersionerhöht sich beiRefresh; Host führt einen In-Place-Tausch ohne Neustart durch; cID-übergreifende Invalidierung tauscht Quell- und Ziel-Token; ein invalidiertes Ziel-Token löstCopyTokenInvalidatedaus und erholt sich automatisch beim nächsten Token-Push (M1); die Watchdog-EntscheidungIsHostDeadstartet einen beendeten/fehlerhaften Host neu und lässt ein neu zugewiesenes Profil in Ruhe (M2). - Integration —
TokenVersionpersistiert + erhöht sich über EF auf echtem Postgres; die Token-Signatur ändert sich bei einem Versions-Bump, selbst wenn der String unverändert bleibt.