Zum Inhalt

App- und Kontoauthentifizierung

Der Authentifizierungsprozess von cTrader Open API basiert auf dem OAuth 2.0-Standard.

Dieses Framework ermöglicht es Drittanbieteranwendungen, begrenzten Zugriff auf einen Dienst zu erhalten, entweder im Namen des Ressourcenbesitzers, indem eine Genehmigungsinteraktion zwischen dem Ressourcenbesitzer und dem Dienst orchestriert wird, oder indem einer Drittanbieteranwendung ermöglicht wird, Zugriff in eigenem Namen zu erhalten.

Authentifizierungsablauf

Gemäß dem OAuth 2.0-Standard erfordert die Kontoauthentifizierung sowohl einen Autorisierungscode als auch ein Zugriffstoken.

Token definieren

Ein Autorisierungscode ist ein kurzfristiges Token, das für eine einzelne cTID ausgestellt wird. Seine Ablaufzeit beträgt eine Minute. Ein Zugriffstoken ist ein langfristiges Token, das es einer Anwendung ermöglicht, Nachrichten an das cTrader-Backend zu senden und von diesem zu empfangen. Nach Erhalt muss ein Autorisierungscode schnell gegen ein Zugriffstoken ausgetauscht werden; danach müssen alle an das cTrader-Backend gesendeten Nachrichten mit dem erhaltenen Zugriffstoken signiert werden, um Ihre Anwendung zu authentifizieren. Die Ablaufzeit eines Zugriffstokens beträgt 2.628.000 Sekunden (ungefähr 30 Tage). Nachdem es abgelaufen ist, kann ein neues Zugriffstoken mithilfe eines Aktualisierungstokens generiert werden. Das Aktualisierungstoken hat keine Ablaufzeit.

Typischerweise sieht der Prozess, wenn jemand Ihre Anwendung zum ersten Mal verwendet, wie folgt aus:

1. Ein Nutzer mit einer bestimmten cTID greift auf Ihre Anwendung zu, wo immer sie bereitgestellt ist; der Nutzer interagiert mit einem Aktionsbutton oder Äquivalent.

2. Die Anwendung verwendet einen eingebetteten Browser (oder ein anderes geeignetes Mittel), um den Nutzer zu einer bestimmten URI umzuleiten, wo er der App die erforderlichen Berechtigungen erteilt.

Vertrauen gewinnen

Bevor Sie den Nutzer zu dieser URI umleiten, stellen Sie sicher, dass der Nutzer Ihrer App vertraut und sich der Tatsache bewusst ist, dass er zusätzliche Berechtigungen erteilen muss.

3. Der Nutzer wird zu einer vordefinierten Umleitungs-URL übertragen. Diese URL enthält das Zugriffstoken als Wert des Abfrageparameters code.

4. Der Nutzer wird entweder von sich aus oder automatisch zur App zurückübertragen. Die App wird über den Wert des Parameters code informiert.

5. Die App sendet eine Anfrage zum Austausch des Autorisierungscodes gegen ein Zugriffstoken an einen bestimmten Endpunkt.

6. Die App erhält eine Antwort, die das Zugriffstoken als Wert des Schlüssels accessToken enthält.

7. Die App sendet die ProtoOAApplicationAuthReq-Nachricht, die die Felder clientId und clientSecret enthält.

8. Die App sendet die ProtoOAGetAccountListByAccessTokenReq-Nachricht, die das Feld accessToken enthält. Die Antwort (ProtoOAGetAccountListByAccessTokenRes) enthält das wiederholte Feld ctidTraderAccountId.

9. Nach Erhalt einer Antwort sendet die App die ProtoOAAccountAuthReq-Nachricht, die die Felder ctidTraderAccountId und accessToken enthält.

Danach sollte der Nutzer unter dem Konto authentifiziert sein, dessen ctidTraderAccountId mit der in Schritt 8 angegebenen ctidTraderAccountId übereinstimmt.

Das nachstehende Diagramm erklärt, wie der grundlegende Authentifizierungsablauf aus der Perspektive Ihrer Open API-Anwendung funktioniert.

graph TB
  A([Leiten Sie den Benutzer <br/> zu einer bestimmten URI weiter]) ==> B([Empfangen Sie den <br/> Autorisierungscode]);
  B ==> C([Senden Sie eine Anfrage <br/> zum Erhalt eines <br/> Zugriffscodes]);
  C ==> D([Senden Sie die <br/> Nachricht <br/> ProOAApplicationAuthReq]);
  D ==> E([Senden Sie die <br/> Nachricht <br/> ProtoOAAccountAuthReq]);

In den folgenden Unterabschnitten erklären wir die wichtigsten Schritte des Authentifizierungsablaufs im Detail.

Hinzufügen einer Umleitungs-URI

Wie zuvor gezeigt, muss Ihre App einen Autorisierungscode erhalten, nachdem ein Nutzer zu einer bestimmten Umleitungs-URI gesendet wurde. Diese URI enthält den Autorisierungscode als Wert des Abfrageparameters code.

Um eine neue Umleitungs-URI hinzuzufügen, gehen Sie wie folgt vor:

1. Öffnen Sie die Seite Anwendungen im Open API-Portal.

2. Wählen Sie den Button Bearbeiten in der Zeile mit der Anwendung aus, zu der Sie eine Umleitungs-URL hinzufügen möchten.

3. Scrollen Sie im neu erschienenen Bildschirm nach unten zum Abschnitt Umleitungs-URIs.

4. Fügen Sie eine Umleitungs-URL in ein verfügbares leeres Texteingabefeld ein. Wenn keine verfügbaren Felder angezeigt werden, wählen Sie den Button Umleitungs-URI hinzufügen aus.

5. Wählen Sie den Button Speichern am unteren Rand der Seite aus, um Ihre Änderungen zu übernehmen.

Umleitungs-URIs verwalten

Die allererste Umleitungs-URI ist für den Playground-Dienst, mit dem Sie Ihre Anwendung testen können, bevor Sie regulären Nutzern Zugriff darauf gewähren. Sie darf niemals für eine Produktionsanwendung verwendet werden. Sie können bei Bedarf eine unbegrenzte Anzahl von Umleitungs-URIs hinzufügen.

Erhalten des Autorisierungscodes

Um einen Autorisierungscode für eine bestimmte cTID zu erhalten, muss Ihre App einen Nutzer zu der folgenden URI senden.

https://id.ctrader.com/my/settings/openapi/grantingaccess/?client_id={clientId}&redirect_uri={your_redirectURI}&scope={scope}&product=web

Hinweis

In dieser Phase muss der Nutzer Ihrer Anwendung oder Ihrem Dienst die Erlaubnis erteilen, auf seine Handelskonten zuzugreifen. Daher ist es unerlässlich, dass Sie dem Nutzer ein vollständiges Verständnis davon vermitteln, was die Nutzung Ihrer Anwendung oder Ihres Dienstes in Bezug auf Berechtigungen, Datenspeicherung und Datenverarbeitung erfordert.

Diese URI hat die folgenden Abfrageparameter.

Parameter Erforderlich? Definition
client_id Ja Die eindeutige Kennung Ihrer Open API-Anwendung.
redirect_uri Ja Ein gültiger Umleitungs-URI, der in den Einstellungen Ihrer Anwendung angegeben ist.
scope Ja Der Umfang der Berechtigungen, die Sie Ihrer Anwendung erteilen möchten. Die folgenden Werte werden akzeptiert:
accounts. Es wird nur schreibgeschützter Zugriff gewährt. Ihre Anwendung kann auf Kontoinformationen und Statistiken zugreifen; die Durchführung von Handelsoperationen ist nicht möglich.
trading. Es wird voller Zugriff auf Kontoinformationen und Statistiken sowie alle zulässigen Handelsoperationen gewährt.
product Nein Wenn dieser Parameter angegeben und auf web gesetzt ist, fehlen auf dem Autorisierungsbildschirm die Kopf- und Fußzeile, wodurch er auf mobilen Geräten besser aussieht. Obwohl der Parameter optional ist, empfehlen wir, ihn auf web zu setzen.

Um Ihre client_id anzuzeigen, gehen Sie zur Seite Anwendungen und wählen Sie den Button Ansicht in der Spalte Anmeldedaten.

Nachdem ein Nutzer an den oben genannten URI gesendet wurde (und solange beide Parameter gültig sind), sollte er einen Anmelde-/Registrierungsbildschirm sehen, der ihn auffordert, sich unter seiner cTID zu autorisieren. Anschließend wird dem Nutzer ein Dialogfeld angezeigt, in dem er der Anwendung den Zugriff auf ein oder mehrere mit seiner cTID verknüpfte Konten erlauben kann.

Wenn der Nutzer den Button Zugriff erlauben auswählt, wird er zu dem redirect_uri weitergeleitet, den Sie ursprünglich angegeben hatten. Wie im folgenden Beispiel gezeigt, wird der Autorisierungscode diesem URI als Abfrageparameter hinzugefügt.

https://my-redirect-uri.com/?code=123ASDASffdg_as234_GCllkoq14adRB7_tvN

An diesem Punkt müsste Ihre Anwendung auf den Wert des Parameters code zugreifen und ihn speichern. Er muss schnell gegen ein Zugriffstoken ausgetauscht werden, bevor der Autorisierungscode abläuft.

Zusätzliche Konten

Wenn ein Nutzer zusätzliche Konten erstellt, nachdem er die oben beschriebenen Aktionen abgeschlossen hat, werden diese Konten nicht innerhalb der Anwendung autorisiert. Stattdessen müsste der Nutzer zurück zu der oben angegebenen URL weitergeleitet werden, damit er der Anwendung Zugriff auf alle zusätzlichen Konten gewähren kann, die er seit der letzten Anmeldung erstellt hat.

Authentifizierung über Google

Wenn der oben genannte URI über WebView geöffnet wird und der Nutzer Google zur Anmeldung wählt, zeigt Google eine Seite Zugriff blockiert an, die den Nutzer daran hindert, fortzufahren.

Um dies zu verhindern, stellen Sie sicher, dass die user-agent-Signatur des Geräts, das die Seite öffnet, wie folgt aussieht.

'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'

Ein Zugriffstoken erhalten

Um ein Zugriffstoken zu erhalten, führen Sie den folgenden REST-API-Aufruf durch.

Relative URL

Die Anfrage-URL ist relativ zu https://openapi.ctrader.com.

Methode URL
GET apps/token

Diese Anfrage enthält die folgenden Abfrageparameter.

Parameter Erforderlich? Definition
grant_type Ja Der Typ des Tokens, das an diesen Endpunkt gesendet wird. Die folgenden Werte werden akzeptiert.
authorization_code. Ein Autorisierungscode wird an den Endpunkt gesendet, um ihn gegen ein Zugriffstoken auszutauschen.
refresh_token. Ein Aktualisierungstoken wird an den Endpunkt gesendet, um ein bestehendes Zugriffstoken zu aktualisieren.
code Nein Das Token, das an den Endpunkt gesendet wird. Dieser Parameter ist obligatorisch, wenn grant_type=authorization_code.
redirect_uri Nein Ein gültiger Umleitungs-URI, der in den Einstellungen Ihrer Anwendung angegeben ist. Dieser Parameter ist obligatorisch, wenn grant_type=authorization_code.
client_id Ja Die eindeutige Kennung Ihrer Open API-Anwendung.
client_secret Ja Der geheime Schlüssel, der Ihrer Open API-Anwendung zugewiesen ist.

Das Anforderungsbeispiel finden Sie unten.

curl -X GET 'https://openapi.ctrader.com/apps/token?grant_type=authorization_code&code=0ssdgds98as9_QSF56FVC_22dfdf&redirect_uri=https://spotware.com&client_id=5430012&client_secret=012sds23dlkjQsd' -H 'Accept: application/json' -H 'Content-Type: application/json'

Um Ihren client_secret anzuzeigen, kehren Sie zur Seite Anwendungen zurück und wählen Sie den Button Ansicht in der Spalte Anmeldedaten.

Bei einer erfolgreichen Anfrage sollten Sie eine Antwort mit den folgenden Schlüsseln erhalten.

Schlüssel Werttyp Definition
"accessToken" string Das Zugriffstoken, das Ihre Anwendung zur Authentifizierung der an cTrader Open API gesendeten Nachrichten verwenden wird.
"tokenType" string Der Typ des Zugriffstokens ("bearer" sollte der Wert dieses Schlüssels sein, da der REST-Standard zur Durchführung der Anfrage verwendet wird).
"expiresIn" integer Die Anzahl der Sekunden, die vergehen müssen, bevor das Zugriffstoken abläuft (standardmäßig entspricht der Wert dieses Schlüssels 2628000).
"refreshToken" string Das Aktualisierungstoken, das zur Erneuerung des Zugriffstokens verwendet werden muss, sobald es abläuft. Das Aktualisierungstoken selbst hat keine Ablaufzeit.
"errorCode" string/null Der Fehlercode, der beschreibt, warum eine Anfrage nicht erfolgreich war. Bei einer erfolgreichen Anfrage sollte der Wert dieses Schlüssels null sein.
"description" string/null Die Beschreibung eines Fehlers, der während einer nicht erfolgreichen Anfrage aufgetreten ist. Bei einer erfolgreichen Anfrage sollte der Wert dieses Schlüssels null sein.

Ein Beispiel für eine erfolgreiche Antwort finden Sie im folgenden Ausschnitt.

{
    "accessToken":"mos8Bw3D4EG0fRPd4Eqq0JxaFT4zjd8e4YijNezh_ag",
    "tokenType":"bearer",
    "expiresIn":2628000,
    "refreshToken":"VCuafFhy81AFZjsWkbuEzdOhhRj5YTWz8fWUwHam7KM",
    "errorCode":null,
    "description":null,
}

Die erforderlichen ProtoBuf-Nachrichten senden

Nach Erhalt eines gültigen Zugriffscodes muss Ihre Anwendung die Nachrichten ProtoOAApplicationAuthReq, ProtoOAGetAccountListByAccessTokenReq und ProtoOAAccountAuthReq senden. Dies kann wie folgt erfolgen.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
private static RepeatedField<ProtoOACtidTraderAccount> _ctidTraderAccounts;

List<IDisposable> _disposables = new();
_disposables.Add(_client.OfType<ProtoOAGetAccountListByAccessTokenRes>().Subscribe(OnAccountIdReceived));

private static void OnAccountIdReceived(ProtoOAGetAccountListByAccessTokenRes response)
{

    Console.WriteLine($"\nMessage Received:\n{response}");

    _ctidTraderAccounts = response.CtidTraderAccount;

    var accountAuthReq = new ProtoOAAccountAuthReq
    {
        CtidTraderAccountId = (long)_ctidTraderAccounts[0].CtidTraderAccountId,
        AccessToken = _token.AccessToken,
    };

    _client.SendMessage(accountAuthReq);

}

var _client = new OpenClient(host, ApiInfo.Port, TimeSpan.FromSeconds(10), useWebSocket: false);
var applicationAuthReq = new ProtoOAApplicationAuthReq
{
    ClientId = {your_client_id}, // Add your client ID here
    ClientSecret = {your_app_secret}, // Add your app secret here
};
await _client.SendMessage(applicationAuthReq);
await Task.Delay(5000);
var getAccountListByAccessToken = new ProtoOAGetAccountListByAccessTokenReq 
{
    AccessToken = {access_token} // Add your access token here
}
var accountAuthReq = new ProtoOAAccountAuthReq 
{
    ctidTraderAccountId = {account_id}, // Add the ctidTraderAccountId of the account you want to authorize here
    AccessToken = {access_token} // Add your access token here
};
await _client.SendMessage(accountAuthReq);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
currentAccountId = None
client = Client(EndPoints.PROTOBUF_LIVE_HOST if hostType.lower() == "live" else EndPoints.PROTOBUF_DEMO_HOST, EndPoints.PROTOBUF_PORT, TcpProtocol)

def connected(client): # Callback for client connection
    print("\nConnected")
    request = ProtoOAApplicationAuthReq()
    request.clientId = appClientId
    request.clientSecret = appClientSecret
    deferred = client.send(request)



def disconnected(client, reason): # Callback for client disconnection
    print("\nDisconnected: ", reason)

def onMessageReceived(client, message): # Callback for receiving all messages
    global currentAccountId
    if message.payloadType in [ProtoOASubscribeSpotsRes().payloadType, ProtoOAAccountLogoutRes().payloadType, ProtoHeartbeatEvent().payloadType]:
        return
    elif message.payloadType == ProtoOAApplicationAuthRes().payloadType:
        print("API Application authorized\n")
        if currentAccountId is not None:
            sendProtoOAAccountAuthReq()
            return
        accountListReq = ProtoOAGetAccountListByAccessTokenReq()
        accountListReq.accessToken = accessToken
        deferred = client.send(accountListReq)
    elif message.payloadType == ProtoOAGetAccountListByAccessTokenRes().payloadType:
        protoOAGetAccountListByAccessTokenRes = Protobuf.extract(message)
        currentAccountId = int(protoOAGetAccountListByAccessTokenRes.ctidTraderAccount[0].ctidTraderAccountId)
        accountAuthReq = ProtoOAAccountAuthReq()
        accountAuthReq.ctidTraderAccountId = currentAccountId
        accountAuthReq.accessToken = accessToken
        deferred = client.send(accountAuthReq)
    elif message.payloadType == ProtoOAAccountAuthRes().payloadType:
        protoOAAccountAuthRes = Protobuf.extract(message)
        print(f"Account {protoOAAccountAuthRes.ctidTraderAccountId} has been authorized\n")
        print("This acccount will be used for all future requests\n")
    else:
        print("Message received: \n", Protobuf.extract(message))
    reactor.callLater(3, callable=executeUserCommand)

def onError(failure): # Call back for errors
    print("Message Error: ", failure)
    reactor.callLater(3, callable=executeUserCommand)

Das Zugriffstoken aktualisieren

Nachdem ein Zugriffstoken abgelaufen ist, müssen Sie es mit dem refreshToken erneuern, den Sie zuvor erhalten haben. Sie können diese Aktion über zwei verschiedene Methoden durchführen.

Eine HTTP-Anfrage senden

Um ein neues Zugriffstoken (und anschließend ein neues Aktualisierungstoken) zu erhalten, können Sie dieselbe HTTP-Anfrage durchführen, die oben behandelt wurde. Wie im folgenden Beispiel gezeigt, müssten Sie den Abfrageparameter grant_type auf refresh_token setzen.

curl -X POST 'https://openapi.ctrader.com/apps/token?grant_type=refresh_token&refresh_token=asdXCVCVAS_218kjashf_asdasd2ASD_223x&client_id=5430012&client_secret=012sds23dlkjQsd' -H 'Accept: application/json' -H 'Content-Type: application/json'

Sie erhalten eine Antwort, die die neuen Werte der Schlüssel accessToken und refreshToken enthält. Sie können diese neuen Werte sicher verwenden, während die alten Werte derselben Schlüssel automatisch ungültig gemacht werden.

Senden einer Protobuf-Nachricht

Alternativ können Sie die Nachricht ProtoOARefreshTokenReq senden und die Nachricht ProtoOARefreshTokenRes mit neuen gültigen Token erhalten.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
_disposables.Add(_client.OfType<ProtoOARefreshTokenRes>().Subscribe(OnRefreshTokenResponse));
private static void OnRefreshTokenResponse(ProtoOARefreshTokenRes response) 
{
    _token = new Token 
    {
        AccessToken = response.AccessToken,
        RefreshToken = response.RefreshToken,
        ExpiresIn = DateTimeOffset.FromUnixTimeMilliseconds(response.ExpiresIn),
        TokenType = response.TokenType,
    }
}
var refreshTokenReq = new ProtoOARefreshTokenReq
    {
        refreshToken = {your_refresh_token}, // Add your refresh token here
    };
await _client.SendMessage(applicationAuthReq);
1
newToken = auth.refreshToken("refresh_Token")

Verwenden Sie den Playground

Der Playground bietet eine schnelle Möglichkeit, ein Zugriffstoken für Ihre eigene cTID zu erhalten, sodass Sie Ihre App schnell und einfach entwickeln und testen können, bevor Sie sie an Ihre Zielgruppe verteilen.

Um auf den Playground zuzugreifen, gehen Sie zur Seite Anwendungen und wählen Sie den Button Playground aus. Wählen Sie im neu erschienenen Fenster den Umfang der Anwendung aus und klicken Sie auf den Button Token abrufen.

Danach sollten Sie die folgende Seite sehen.

Sie können das Zugriffstoken und das Aktualisierungstoken verwenden, um Nachrichten an die API zu senden, während Sie unter Ihrer eigenen cTID authentifiziert sind.