Vai al contenuto

Autenticazione dell'app e del conto

Il processo di autenticazione dell'Open API di cTrader si basa sullo standard OAuth 2.0.

Questo framework consente alle applicazioni di terze parti di ottenere un accesso limitato a un servizio per conto del proprietario della risorsa, orchestrando un'interazione di approvazione tra il proprietario della risorsa e il servizio, oppure consentendo a un'applicazione di terze parti di ottenere l'accesso per proprio conto.

Flusso di autenticazione

Come previsto dallo standard OAuth 2.0, l'autenticazione del conto richiede sia un codice di autorizzazione che un token di accesso.

Definisci i token

Un codice di autorizzazione è un token a breve termine emesso per un singolo cTID. Il suo periodo di scadenza è di un minuto. Un token di accesso è un token a lungo termine che consente a un'applicazione di inviare e ricevere messaggi da e verso il backend di cTrader. Dopo averlo ricevuto, un codice di autorizzazione deve essere rapidamente scambiato con un token di accesso; successivamente, tutti i messaggi inviati al backend di cTrader devono essere firmati con il token di accesso ricevuto per autenticare la tua applicazione. Il periodo di scadenza di un token di accesso è di 2.628.000 secondi (circa 30 giorni). Dopo la scadenza, è possibile generare un nuovo token di accesso utilizzando un token di aggiornamento. Il token di aggiornamento non ha un periodo di scadenza.

In genere, il processo di un nuovo utente che inizia a utilizzare la tua applicazione per la prima volta si svolge come segue:

1. Un utente con un determinato cTID accede alla tua applicazione ovunque sia distribuita; l'utente interagisce con un pulsante di azione o equivalente.

2. L'applicazione utilizza un browser incorporato (o qualsiasi altro mezzo adatto) per reindirizzare l'utente a un URI specifico dove concederà all'app le autorizzazioni necessarie.

Ottieni fiducia

Prima di reindirizzare l'utente a questo URI, assicurati che l'utente si fidi della tua app e sia consapevole del fatto che dovrà fornire autorizzazioni aggiuntive.

3. L'utente viene trasferito a un URL di reindirizzamento predefinito. Questo URL contiene il token di accesso come valore del parametro di query code.

4. L'utente viene riportato all'app di propria iniziativa o automaticamente. L'app viene informata del valore del parametro code.

5. L'app invia una richiesta per scambiare il codice di autorizzazione con un token di accesso a un endpoint specifico.

6. L'app riceve una risposta contenente il token di accesso come valore della chiave accessToken.

7. L'app invia il messaggio ProtoOAApplicationAuthReq contenente i campi clientId e clientSecret.

8. L'app invia il messaggio ProtoOAGetAccountListByAccessTokenReq contenente il campo accessToken. La risposta (ProtoOAGetAccountListByAccessTokenRes) contiene il campo ripetuto ctidTraderAccountId.

9. Dopo aver ricevuto una risposta, l'app invia il messaggio ProtoOAAccountAuthReq contenente i campi ctidTraderAccountId e accessToken.

Successivamente, l'utente dovrebbe essere autenticato sotto il conto il cui ctidTraderAccountId corrisponde al ctidTraderAccountId fornito durante il passaggio 8.

Il diagramma seguente spiega come funziona il flusso di autenticazione di base dal punto di vista della tua applicazione Open API.

graph TB
  A([Reindirizza l'utente <br/> a un URI specifico]) ==> B([Ricevi il codice <br/> di autorizzazione]);
  B ==> C([Invia una richiesta <br/> per ottenere <br/> un codice di accesso]);
  C ==> D([Invia il <br/> messaggio <br/> ProOAApplicationAuthReq]);
  D ==> E([Invia il <br/> messaggio <br/> ProtoOAAccountAuthReq]);

Nelle sottosezioni seguenti, spieghiamo in dettaglio i passaggi chiave del flusso di autenticazione.

Aggiungere un URI di reindirizzamento

Come mostrato in precedenza, la tua app deve ottenere un codice di autorizzazione dopo che un utente viene inviato a un determinato URI di reindirizzamento. Questo URI includerà il codice di autorizzazione come valore del parametro di query code.

Per aggiungere un nuovo URI di reindirizzamento, procedi come segue:

1. Apri la pagina Applicazioni nel portale Open API.

2. Seleziona il pulsante Modifica nella riga con l'applicazione a cui desideri aggiungere un URL di reindirizzamento.

3. Nella schermata appena apparsa, scorri verso il basso fino alla sezione URI di reindirizzamento.

4. Aggiungi un URL di reindirizzamento in un campo di input di testo vuoto disponibile. Se non vengono mostrati campi disponibili, seleziona il pulsante Aggiungi URI di reindirizzamento.

5. Seleziona il pulsante Salva in fondo alla pagina per applicare le modifiche.

Gestisci gli URI di reindirizzamento

Il primo URI di reindirizzamento è per il servizio Playground che ti consente di testare la tua applicazione prima di dare accesso agli utenti normali. Non deve mai essere utilizzato per un'applicazione in produzione. Puoi aggiungere un numero illimitato di URI di reindirizzamento, se necessario.

Ottenere il codice di autorizzazione

Per ricevere un codice di autorizzazione per un cTID specifico, la tua app dovrà inviare un utente al seguente URI.

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

Nota

In questa fase, l'utente dovrà autorizzare la tua applicazione o servizio ad accedere ai suoi conti di trading. Di conseguenza, è fondamentale che tu fornisca all'utente una comprensione completa di ciò che l'utilizzo della tua applicazione o servizio richiederà in termini di autorizzazioni, archiviazione dei dati ed elaborazione dei dati.

Questo URI ha i seguenti parametri di query.

Parametro Obbligatorio? Definizione
client_id Sì L'identificatore univoco della tua applicazione Open API.
redirect_uri Sì Un URI di reindirizzamento valido specificato nelle impostazioni della tua applicazione.
scope Sì L'ambito delle autorizzazioni che desideri vengano concesse alla tua applicazione. Sono accettati i seguenti valori:
accounts. Viene concesso l'accesso in sola visualizzazione. La tua applicazione potrà accedere alle informazioni e alle statistiche del conto; non sarà possibile eseguire operazioni di trading.
trading. Viene concesso l'accesso completo alle informazioni e alle statistiche del conto, nonché a tutte le operazioni di trading consentite.
product No Se questo parametro è specificato e impostato su web, la schermata di autorizzazione non presenta l'intestazione e il piè di pagina, il che la rende migliore sui dispositivi mobili. Sebbene il parametro sia opzionale, consigliamo di impostarlo su web.

Per visualizzare il tuo client_id, vai alla pagina Applicazioni e seleziona il pulsante Visualizza nella colonna Credenziali.

Dopo che un utente viene inviato all'URI sopra indicato (e purché entrambi i parametri siano validi), dovrebbe vedere una schermata di accesso/registrazione che lo invita ad autorizzarsi con il proprio cTID. Successivamente, all'utente verrà mostrata una finestra di dialogo in cui potrà autorizzare l'applicazione ad accedere a uno o più conti collegati al proprio cTID.

Quando l'utente seleziona il pulsante Consenti accesso, verrà reindirizzato all'redirect_uri che avevi specificato originariamente. Come mostrato nell'esempio seguente, il codice di autorizzazione verrà aggiunto a questo URI come parametro di query.

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

A questo punto, la tua applicazione dovrebbe accedere e memorizzare il valore del parametro code. Deve essere rapidamente scambiato con un token di accesso prima che il codice di autorizzazione scada.

Account aggiuntivi

Se un utente crea conti aggiuntivi dopo aver completato le azioni descritte sopra, questi conti non saranno autorizzati all'interno dell'applicazione. Invece, l'utente dovrebbe essere reindirizzato nuovamente all'URL fornito sopra in modo da poter dare all'applicazione l'accesso a eventuali conti aggiuntivi creati dall'ultimo accesso.

Autenticazione tramite Google

Se l'URI sopra indicato viene aperto tramite WebView e l'utente sceglie Google per accedere, Google visualizzerà una pagina Accesso bloccato, impedendo all'utente di procedere ulteriormente.

Per evitare ciò, assicurati che la firma user-agent del dispositivo che apre la pagina sia la seguente.

'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'

Ottenere un token di accesso

Per ottenere un token di accesso, esegui la seguente chiamata API REST.

URL relativo

L'URL della richiesta è relativo a https://openapi.ctrader.com.

Metodo URL
GET apps/token

Questa richiesta include i seguenti parametri di query.

Parametro Obbligatorio? Definizione
grant_type Sì Il tipo di token inviato a questo endpoint. Sono accettati i seguenti valori.
authorization_code. Un codice di autorizzazione viene inviato all'endpoint per scambiarlo con un token di accesso.
refresh_token. Un token di aggiornamento viene inviato all'endpoint per aggiornare un token di accesso esistente.
code No Il token inviato all'endpoint. Questo parametro è obbligatorio se grant_type=authorization_code.
redirect_uri No Un URI di reindirizzamento valido specificato nelle impostazioni della tua applicazione. Questo parametro è obbligatorio se grant_type=authorization_code.
client_id Sì L'identificatore univoco della tua applicazione Open API.
client_secret Sì La chiave segreta assegnata alla tua applicazione Open API.

L'esempio di richiesta è riportato di seguito.

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'

Per visualizzare il tuo client_secret, torna alla pagina Applicazioni e seleziona il pulsante Visualizza nella colonna Credenziali.

In caso di richiesta riuscita, dovresti ricevere una risposta con le seguenti chiavi.

Chiave Tipo di valore Definizione
"accessToken" string Il token di accesso che la tua applicazione utilizzerà per autenticare i messaggi inviati a cTrader Open API.
"tokenType" string Il tipo di token di accesso ("bearer" dovrebbe essere il valore di questa chiave poiché viene utilizzato lo standard REST per effettuare la richiesta).
"expiresIn" integer Il numero di secondi che devono trascorrere prima che il token di accesso scada (per impostazione predefinita, il valore di questa chiave è pari a 2628000).
"refreshToken" string Il token di aggiornamento che deve essere utilizzato per rinnovare il token di accesso una volta scaduto. Il token di aggiornamento non ha un tempo di scadenza.
"errorCode" string/null Il codice di errore che descrive il motivo per cui una richiesta non è andata a buon fine. Per una richiesta riuscita, il valore di questa chiave dovrebbe essere null.
"description" string/null La descrizione di un errore che si è verificato durante una richiesta non riuscita. Per una richiesta riuscita, il valore di questa chiave dovrebbe essere null.

Per un esempio di risposta riuscita, vedi lo snippet qui sotto.

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

Invia i messaggi ProtoBuf richiesti

Dopo aver ricevuto un codice di accesso valido, la tua applicazione dovrà inviare i messaggi ProtoOAApplicationAuthReq, ProtoOAGetAccountListByAccessTokenReq e ProtoOAAccountAuthReq. Questo può essere fatto come segue.

 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)

Aggiorna il token di accesso

Dopo la scadenza di un token di accesso, dovrai rinnovarlo utilizzando il refreshToken che hai ricevuto in precedenza. Puoi eseguire questa azione tramite due metodi diversi.

Invia una richiesta HTTP

Per ottenere un nuovo token di accesso (e, successivamente, un nuovo token di aggiornamento), puoi eseguire la stessa richiesta HTTP trattata sopra. Come mostrato nell'esempio seguente, dovresti impostare il parametro di query grant_type su refresh_token.

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'

Riceverai una risposta contenente i nuovi valori delle chiavi accessToken e refreshToken. Puoi utilizzare in sicurezza questi nuovi valori mentre i vecchi valori delle stesse chiavi vengono automaticamente invalidati.

Invia un messaggio Protobuf

In alternativa, puoi inviare il messaggio ProtoOARefreshTokenReq e ricevere il messaggio ProtoOARefreshTokenRes contenente nuovi token validi.

 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")

Usa il Playground

Il Playground fornisce un mezzo rapido per ottenere un token di accesso per il tuo cTID, consentendoti di sviluppare e testare rapidamente e facilmente la tua app prima di distribuirla tra il suo pubblico di destinazione.

Per accedere al Playground, vai alla pagina Applicazioni e seleziona il pulsante Playground. Nella finestra appena apparsa, seleziona l'ambito dell'applicazione e fai clic sul pulsante Ottieni token.

Successivamente, dovresti vedere la seguente pagina.

Puoi utilizzare il token di accesso e il token di aggiornamento per inviare messaggi all'API mentre sei autenticato con il tuo cTID.