Skip to content

Commerzbank photoTAN: current TAN mechanism remains 999 while 2-step mechanism is 900 #212

@QHLe

Description

@QHLe

Describe the bug
With Commerzbank photoTAN, the client can end up in a state where the current TAN mechanism is still 999, while the bank-advertised usable two-step mechanism is 900.

This makes the bootstrap/follow-up flow brittle. In particular, code paths such as minimal_interactive_cli_bootstrap() and is_challenge_structured() appear to assume that get_current_tan_mechanism() is always present in get_tan_mechanisms(). For this Commerzbank flow, that assumption does not always hold.

*Bank I tested this with
Name of the bank: Commerzbank
FinTS URL:https://fints.commerzbank.de/fints

Expected behavior
After dialog initialization, the client should be able to continue normally with the bank-advertised usable two-step TAN method.

In this case, once the bank reports 900 and 999 as allowed methods, the flow should be able to continue with 900 (photoTAN) without requiring application-level workarounds.

Code required to reproduce

**Describe the bug**

With Commerzbank photoTAN, the client can end up in a state where the current TAN mechanism is still `999`, while the bank-advertised usable two-step mechanism is `900`.

This makes the bootstrap/follow-up flow brittle. In particular, code paths such as `minimal_interactive_cli_bootstrap()` and `is_challenge_structured()` appear to assume that `get_current_tan_mechanism()` is always present in `get_tan_mechanisms()`. For this Commerzbank flow, that assumption does not always hold.

**Bank I tested this with*
Name of the bank: Commerzbank
FinTS URL:https://fints.commerzbank.de/fints

**Expected behavior**

After dialog initialization, the client should be able to continue normally with the bank-advertised usable two-step TAN method.

In this case, once the bank reports `900` and `999` as allowed methods, the flow should be able to continue with `900` (`photoTAN`) without requiring application-level workarounds.

**Code required to reproduce**
```python
import os
from fints.client import FinTS3PinTanClient, NeedTANResponse
from fints.utils import minimal_interactive_cli_bootstrap

client = FinTS3PinTanClient(
    os.environ["FINTS_BLZ"],
    os.environ["FINTS_USER"],
    os.environ["FINTS_PIN"],
    os.environ["FINTS_SERVER"],
    customer_id=os.environ["FINTS_CUSTOMER_ID"],
    product_id=os.environ["FINTS_PRODUCT_ID"],
    product_version=os.environ["FINTS_PRODUCT_VERSION"],
)

client.set_product(
    os.environ["FINTS_PRODUCT_NAME"],
    os.environ["FINTS_PRODUCT_VERSION"],
)

minimal_interactive_cli_bootstrap(client)

with client:
    if isinstance(client.init_tan_response, NeedTANResponse):
        print(client.init_tan_response.challenge)
        tan = input("TAN: ").strip()
        client.send_tan(client.init_tan_response, tan)

    print("current TAN mechanism:", client.get_current_tan_mechanism())
    print("known TAN mechanisms:", list((client.get_tan_mechanisms() or {}).keys()))
    print(client.get_sepa_accounts())

Log output / error message
WARNING:fints.client:Dialog response: 3920 - Zugelassene Ein- und Zwei-Schritt-Verfahren für den Benutzer. (['900', '999'])
TAN bestaetigt.
System-ID:
Bankseitiger Benutzer:
Aktuelle TAN-Methode: 900
Verfuegbare TAN-Methoden:
{'code': '900', 'name': 'photoTAN'}

Additional context
What worked for me as a workaround was:

initialize the dialog normally
allow the client to start with current mechanism 999
after dialog initialization, explicitly switch to the first real two-step method (900)
continue with the photoTAN challenge
After doing that, dialog initialization and SEPA account retrieval worked.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions