Hilfe
abbrechen
Suchergebnisse werden angezeigt für 
Stattdessen suchen nach 
Meintest du: 

REST-API - CD Secondary Flow

TinTin82
Einsteiger
1 Beiträge

Hi,

ich versuche mich momentan über die comdirect REST Api mit meinem Konto zu verbinden in der Hoffnung einiges automatisieren zu können.

Folgende Schritte funktionieren soweit ich das absehe:

  1. 2.1 OAuth2 Resource Owner Password Credentials Flow
  2. 2.2 Abruf Session-Status
  3. 2.3 Anlage Validierung einer Session-TAN
  4. 2.4 Aktivierung einer Session-TAN

Beim Schritt: "2.5 CD Secondary Flow" bekomme ich einen Fehler zurück:
{"error":"invalid_client","error_description":"Bad client credentials"}

 

Ich verwende libCURL und baue mir den POST wie folgt zusammen:

 

 

/**
** ===================================================
** URL: https://api.comdirect.de/oauth/token
** HTTP-Method: POST
** ===================================================
***/
curl_easy_setopt(curl, CURLOPT_URL, "https://api.comdirect.de/oauth/token");
/* Now specify we want to POST data */
curl_easy_setopt(curl, CURLOPT_POST, 1L);
/* provide a buffer to store errors in */
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);



/**
** ===================================================
** HEADER
** ===================================================
***/
/* Create header according to comdirect api description */
list = curl_slist_append(list, "Accept: application/json");
list = curl_slist_append(list, "Content-Type: application/x-www-form-urlencoded");

curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);

            /**
            ** ===================================================
            ** DATA
            ** ===================================================
            ***/
            /* Create data according to comdirect api description */
            std::string str_DATA;
            char *escaped_field = curl_easy_escape(NULL, "User_********************************", 0);
            str_DATA+= std::string("client_id=")+std::string(escaped_field)+std::string("&");
            curl_free(escaped_field);

            escaped_field = curl_easy_escape(NULL, "********************************", 0);
            str_DATA+= std::string("client_secret=")+std::string(escaped_field)+std::string("&");
            curl_free(escaped_field);

            escaped_field = curl_easy_escape(NULL, "cd_secondary", 0);
            str_DATA+= std::string("grant_type=")+std::string(escaped_field)+std::string("&");
            curl_free(escaped_field);

            escaped_field = curl_easy_escape(NULL, "*****************", 0);
            str_DATA+= std::string("token=")+std::string(escaped_field);
            curl_free(escaped_field);
            curl_easy_setopt(curl, CURLOPT_POSTFIELDS, str_DATA.c_str());


            res = curl_easy_perform(curl);

 

 

Den Wert für das "Access-Token" habe ich aus dem:
2.1 OAuth2 Resource Owner Password Credentials Flow

Die beiden werte "client_id" und "client_secret" habe ich gleich wie beim 
2.1 OAuth2 Resource Owner Password Credentials Flow
gesetzt und von comdirect erhalten beim anmelden für die API.

Kann mir jemand sagen was ich bei diesem POST falsch mache?

Viele Grüße,
TinTin

4 ANTWORTEN

FSQuant
Experte ★
164 Beiträge

Moin,

 

1. Falsches Token verwendet

Das ist wahrscheinlich der Hauptfehler! Der User schreibt:

"Den Wert für das 'Access-Token' habe ich aus dem: 2.1 OAuth2 Resource Owner Password Credentials Flow"

Das ist falsch! Beim CD Secondary Flow muss im token Parameter das Session-Token aus Schritt 2.4 (TAN-Aktivierung) verwendet werden, NICHT das Access-Token aus Schritt 2.1.

2. Fehlender Authorization Header

Beim CD Secondary Flow wird normalerweise zusätzlich der Authorization-Header mit dem Access-Token aus Schritt 2.1 benötigt.

 

 

Probier das mal aus? 😉

FSQuant
Experte ★
164 Beiträge

...kam so übrigens aus ClaudeAI aufs erste Prompt raus 😉

 

svebert
Autor ★
11 Beiträge

Hatte auch das Problem. 
Die Antwort von FSQuant ist falsch. Er hat halt einfach nur AI befragt ohne zu Validieren!

Mein Fehler war, dass ich den Schritt 2.4 vergessen hatte. Der curl Aufruf zur Aktivierung der Session ist so (PATCH): 

curl --location --request PATCH 'https://api.comdirect.de/api/session/clients/<ClientID>/v1/sessions/<SessionID>' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <Access Token>' \
--header 'x-http-request-info: {"clientRequestId":{"sessionId":"<SessionID>","requestId":"123456789"}}' \
--header 'Content-Type: application/json' \
--header 'x-once-authentication-info: {"id":"<TAN-ID>"}' \
--header 'Cookie: qSession=a11705d9.a6f46707e31346968d26a3e' \
--data '{
    "identifier": "<SessionID>",
    "sessionTanActive": true,
    "activated2FA": true
  }'

<Access Token> ist das Access Token aus dem ersten Schritt 2.1
<SessionID> wird mehrfach angegeben und entspricht dem Wert von clientRequestId.sessionId, was du im Schritt 2.2.1 selber gesetzt hast.
<ClientID> ist die Client-ID aus deinen OAuth-Credentials. 
<TAN-ID> bekommst du aus dem vorherigen Schritt (2.3 session validate). Die ID steht im Return Header im x-once-authentication-info Feld. 

Der Aufruf für den Secondary Flow ist nun so (POST)

 
curl --location 'https://api.comdirect.de/oauth/token' \
--header 'Accept: application/json' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Bearer <Access Token>' \
--header 'Cookie: qSession=a11705d9.a6f46707e31346968d26a3e' \
--data-urlencode 'client_id=<Client ID>' \
--data-urlencode 'client_secret=<Client Secret>' \
--data-urlencode 'grant_type=cd_secondary' \
--data-urlencode 'token=<Access Token>'
 

Wichtig ist also, dass unter token das Access Token aus 2.1 kommt. Aber der Aufruf funktioniert nur, wenn mit der PhotoTAN-App die Session (2FA) authorisiert wurde und Schritt 2.4 erfolgreich war. 


Falls wer von Comdirect das hier liest: 
1) Bitte mal die Doku (PDF) aktualisieren und klarer darstellen. 
2) Vllt. mal die API dahingehend überarbeiten, dass in einem Call nicht identische Werte in Header und Body übergeben werden müssen. Das verwirrt nur, weil es völlig unlogisch ist zweimal das gleiche anzugeben.
3) Access Flows vereinfachen. Warum braucht es 4 Calls PLUS einen Swipe in der Photo TAN App um das secondary access token zu erhalten. Also 2FA ist ja supi und soll bitte bleiben. Aber 4 API Calls um letzendlich ein access token zu erhalten ist crazy. Security through obscurity oder was soll das sein?

 

FSQuant
Experte ★
164 Beiträge

Moin svebert,

 

keine Ahnung, warum du dich so aufregst? 

Erstens steht da, dass ich das aus ClaudeAI rauskopiert habe als Antwort aus meinem Workspace, in den ich die Frage von @TinTin82  reinkopiert hatte.

 

Zweitens: Wenn dir der fehlerhafte Ansatz trotzdem ein kleine Inspiration gegeben hat und du es jetzt gelöst hast, ist es ja gut?

 

Drittens: Ich arbeite selbst mit C# und habe eine Client-Lib, die all das für mich kappselt - solltest du auch machen: Du kannst als Pasis die Postman Docu nehmen. Dann musst du dich mit diesen lowlevel Fragen weniger rumschlagen.

 

Zum unteren Teil deines Beitrags:

Deine Wünsche sind gut und nett aber mit den Verbesserungsvorschlägen wirst du hier leider gegen die Wand laufen 🙂

Das mit der Photo-TAN kann man diskutieren... Viel wichtiger wäre, dass die Sessions serverseitig nicht immer wieder regelmäßig gecancelt werden, sonst könnte die App dauerhaft eingeloggt sein....