Ir para o conteúdo

Autenticação de aplicação e conta

O processo de autenticação do Open API da cTrader baseia-se no padrão OAuth 2.0.

Esta estrutura permite que aplicações de terceiros obtenham acesso limitado a um serviço, seja em nome do proprietário do recurso, orquestrando uma interação de aprovação entre o proprietário do recurso e o serviço, seja permitindo que uma aplicação de terceiros obtenha acesso em seu próprio nome.

Fluxo de autenticação

De acordo com o padrão OAuth 2.0, a autenticação da conta requer tanto um código de autorização como um token de acesso.

Definir tokens

Um código de autorização é um token de curto prazo que é emitido para um cTID individual. O seu período de validade é de um minuto. Um token de acesso é um token de longo prazo que permite que uma aplicação envie e receba mensagens de e para o backend do cTrader. Depois de o receber, um código de autorização deve ser rapidamente trocado por um token de acesso; posteriormente, todas as mensagens enviadas para o backend do cTrader têm de ser assinadas com o token de acesso recebido para autenticar a sua aplicação. O período de validade de um token de acesso é de 2.628.000 segundos (aproximadamente 30 dias). Depois de expirado, pode ser gerado um novo token de acesso usando um token de atualização. O token de atualização não tem período de validade.

Normalmente, o processo de alguém novo começar a usar a sua aplicação pela primeira vez é o seguinte:

1. Um utilizador com um determinado cTID acede à sua aplicação onde quer que esteja implementada; o utilizador interage com um botão de ação ou equivalente.

2. A aplicação usa um navegador incorporado (ou qualquer outro meio adequado) para redirecionar o utilizador para um URI específico onde concederá à aplicação as permissões necessárias.

Ganhar confiança

Antes de redirecionar o utilizador para este URI, certifique-se de que o utilizador confia na sua aplicação e está ciente de que precisará de fornecer permissões adicionais.

3. O utilizador é transferido para um URL de redirecionamento predefinido. Este URL contém o token de acesso como o valor do parâmetro de consulta code.

4. O utilizador é transferido de volta para a aplicação por vontade própria ou automaticamente. A aplicação é informada do valor do parâmetro code.

5. A aplicação envia um pedido para trocar o código de autorização por um token de acesso para um endpoint específico.

6. A aplicação recebe uma resposta contendo o token de acesso como o valor da chave accessToken.

7. A aplicação envia a mensagem ProtoOAApplicationAuthReq contendo os campos clientId e clientSecret.

8. A aplicação envia a mensagem ProtoOAGetAccountListByAccessTokenReq contendo o campo accessToken. A resposta (ProtoOAGetAccountListByAccessTokenRes) contém o campo repetido ctidTraderAccountId.

9. Após receber uma resposta, a aplicação envia a mensagem ProtoOAAccountAuthReq contendo os campos ctidTraderAccountId e accessToken.

Posteriormente, o utilizador deve ser autenticado na conta cujo ctidTraderAccountId corresponde ao ctidTraderAccountId fornecido durante o passo 8.

O diagrama abaixo explica como o fluxo de autenticação básico funciona na perspetiva da sua aplicação Open API.

graph TB
  A([Redirecionar o utilizador <br/> para um URI específico]) ==> B([Receber o código de <br/>autorização]);
  B ==> C([Enviar um pedido para obter <br/> um código de acesso]);
  C ==> D([Enviar a mensagem <br/> ProOAApplicationAuthReq <br/>]);
  D ==> E([Enviar a mensagem <br/> ProtoOAAccountAuthReq <br/>]);

Nas subsecções abaixo, explicamos os passos principais do fluxo de autenticação em detalhe.

Adicionar um URI de redirecionamento

Como mostrado anteriormente, a sua aplicação precisa de obter um código de autorização depois de um utilizador ser enviado para um determinado URI de redirecionamento. Este URI incluirá o código de autorização como o valor do parâmetro de consulta code.

Para adicionar um novo URI de redirecionamento, faça o seguinte:

1. Abra a página Aplicações no portal Open API.

2. Selecione o botão Editar na linha com a aplicação à qual pretende adicionar um URL de redirecionamento.

3. No ecrã que aparece, desloque para baixo até à secção URIs de Redirecionamento.

4. Adicione um URL de redirecionamento num campo de entrada de texto vazio disponível. Se não forem mostrados campos disponíveis, selecione o botão Adicionar URI de redirecionamento.

5. Selecione o botão Guardar na parte inferior da página para aplicar as suas alterações.

Gerir URIs de redirecionamento

O primeiro URI de redirecionamento destina-se ao serviço Playground que permite testar a sua aplicação antes de dar acesso aos utilizadores regulares. Nunca deve ser usado para uma aplicação em produção. Pode adicionar um número ilimitado de URIs de redirecionamento, se necessário.

Obter o código de autorização

Para receber um código de autorização para um cTID específico, a sua aplicação precisará de enviar um utilizador para o seguinte URI.

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

Nota

Nesta fase, o utilizador precisará de permitir que a sua aplicação ou serviço aceda às suas contas de negociação. Como resultado, é imperativo que forneça ao utilizador uma compreensão total do que o uso da sua aplicação ou serviço exigirá em termos de permissões, armazenamento de dados e processamento de dados.

Este URI tem os seguintes parâmetros de consulta.

Parâmetro Obrigatório? Definição
client_id Sim O identificador único da sua aplicação Open API.
redirect_uri Sim Um URI de redirecionamento válido especificado nas definições da sua aplicação.
scope Sim O âmbito das permissões que pretende conceder à sua aplicação. São aceites os seguintes valores:
accounts. É concedido acesso apenas para visualização. A sua aplicação poderá aceder a informações e estatísticas da conta; não será possível realizar operações de negociação.
trading. É concedido acesso total a informações e estatísticas da conta, bem como a todas as operações de negociação permitidas.
product Não Se este parâmetro for especificado e definido como web, o ecrã de autorização não terá cabeçalho nem rodapé, o que o torna mais adequado para dispositivos móveis. Embora o parâmetro seja opcional, recomendamos defini-lo como web.

Para ver o seu client_id, aceda à página Aplicações e selecione o botão Ver na coluna Credenciais.

Depois de um utilizador ser enviado para o URI acima (e desde que ambos os parâmetros sejam válidos), deverá ver um ecrã de início de sessão/registo a solicitar autorização com o seu cTID. Em seguida, será apresentada uma caixa de diálogo ao utilizador onde poderá permitir que a aplicação obtenha acesso a uma ou mais contas associadas ao seu cTID.

Quando o utilizador selecionar o botão Permitir acesso, será redirecionado para o redirect_uri que especificou originalmente. Como mostrado no exemplo abaixo, o código de autorização será adicionado a este URI como um parâmetro de consulta.

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

Neste momento, a sua aplicação precisará de aceder e armazenar o valor do parâmetro code. Deve ser rapidamente trocado por um token de acesso antes que o código de autorização expire.

Contas adicionais

Se um utilizador criar contas adicionais após concluir as ações descritas acima, estas contas não serão autorizadas dentro da aplicação. Em vez disso, o utilizador precisará de ser redirecionado de volta para o URL fornecido acima para poder dar à aplicação acesso a quaisquer contas adicionais que tenha criado desde o último início de sessão.

Autenticação via Google

Se o URI acima for aberto através do WebView e o utilizador escolher o Google para iniciar sessão, o Google apresentará uma página Acesso bloqueado, impedindo o utilizador de prosseguir.

Para evitar isto, certifique-se de que a assinatura user-agent do dispositivo que abre a página é a seguinte.

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

Obter um token de acesso

Para obter um token de acesso, execute a seguinte chamada da API REST.

URL relativa

O URL do pedido é relativo a https://openapi.ctrader.com.

Método URL
GET apps/token

Este pedido inclui os seguintes parâmetros de consulta.

Parâmetro Obrigatório? Definição
grant_type Sim O tipo de token enviado para este endpoint. São aceites os seguintes valores.
authorization_code. É enviado um código de autorização para o endpoint para o trocar por um token de acesso.
refresh_token. É enviado um token de atualização para o endpoint para atualizar um token de acesso existente.
code Não O token enviado para o endpoint. Este parâmetro é obrigatório se grant_type=authorization_code.
redirect_uri Não Um URI de redirecionamento válido especificado nas definições da sua aplicação. Este parâmetro é obrigatório se grant_type=authorization_code.
client_id Sim O identificador único da sua aplicação Open API.
client_secret Sim A chave secreta atribuída à sua aplicação Open API.

O exemplo do pedido pode ser encontrado abaixo.

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'

Para ver o seu client_secret, volte à página Aplicações e selecione o botão Ver na coluna Credenciais.

Após um pedido bem-sucedido, deverá receber uma resposta com as seguintes chaves.

Chave Tipo de valor Definição
"accessToken" string O token de acesso que a sua aplicação utilizará para autenticar as mensagens enviadas para o Open API da cTrader.
"tokenType" string O tipo de token de acesso (bearer"" deve ser o valor desta chave, uma vez que é utilizado o padrão REST para fazer o pedido).
"expiresIn" integer O número de segundos que devem passar antes que o token de acesso expire (por predefinição, o valor desta chave é igual a 2628000).
"refreshToken" string O token de atualização que deve ser utilizado para renovar o token de acesso quando este expirar. O token de atualização não tem tempo de expiração.
"errorCode" string/null O código de erro que descreve por que motivo um pedido não foi bem-sucedido. Para um pedido bem-sucedido, o valor desta chave deve ser null.
"description" string/null A descrição de um erro que ocorreu durante um pedido mal sucedido. Para um pedido bem-sucedido, o valor desta chave deve ser null.

Para um exemplo de uma resposta bem-sucedida, consulte o excerto abaixo.

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

Enviar as mensagens ProtoBuf necessárias

Após receber um código de acesso válido, a sua aplicação terá de enviar as mensagens ProtoOAApplicationAuthReq, ProtoOAGetAccountListByAccessTokenReq e ProtoOAAccountAuthReq. Isto pode ser feito da seguinte forma.

 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)

Atualizar o token de acesso

Depois de um token de acesso expirar, terá de o renovar utilizando o refreshToken que recebeu anteriormente. Pode efetuar esta ação através de dois métodos diferentes.

Enviar um pedido HTTP

Para obter um novo token de acesso (e, subsequentemente, um novo token de atualização), pode efetuar o mesmo pedido HTTP abordado acima. Como mostrado no exemplo abaixo, terá de definir o parâmetro de consulta grant_type como 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'

Receberá uma resposta contendo os novos valores das chaves accessToken e refreshToken. Pode utilizar com segurança estes novos valores enquanto os valores antigos das mesmas chaves são automaticamente invalidados.

Enviar uma mensagem Protobuf

Em alternativa, pode enviar o ProtoOARefreshTokenReq e receber a mensagem ProtoOARefreshTokenRes contendo novos tokens válidos.

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

Utilizar o Playground

O Playground fornece um meio rápido para obter um token de acesso para o seu próprio cTID, permitindo-lhe desenvolver e testar a sua aplicação de forma rápida e fácil antes de a distribuir entre o seu público-alvo.

Para aceder ao Playground, aceda à página Applications e selecione o botão Playground. Na janela que aparece, selecione o âmbito da aplicação e clique no botão Get token.

Depois, deverá ver a seguinte página.

Pode utilizar o token de acesso e o token de atualização para enviar mensagens para a API enquanto autenticado com o seu próprio cTID.