DKB New Authentication Methods
Describe the bug I wanted to log into my bank account via this app (https://flathub.org/apps/org.tabos.saldo). The problem is that the TAN2Go procedure has been completely discontinued by the bank since 24.11.2024. There is only the pushTAN or chipTAN procedure left. However, since I have not activated or do not need a chipTAN via the bank, I can only access my account via the pushTAN procedure. Unfortunately, this option is not offered in the app. The author of this app has forwarded me to you and I should report the problem here.
*Bank I tested this with Name of the bank: Deutsche Kreditbank Berlin (DKB) AG FinTS URL: https://fints.dkb.de/fints
Expected behavior Login to my Bank-Accout via App with the pushTAN procedure.
Can someone look into the problem and maybe do something about it?
Just wanted to add, that the Saldo App does work great with my DKB bank account via chipTAN. I'd also appreciate to have ~~TAN2Go~~ pushTAN added but please don't break chipTAN on that way. ;)
edit: Apologies! I got the app-based methods mixed up.
Just wanted to add, that the Saldo App does work great with my DKB bank account via chipTAN. I'd also appreciate to have TAN2Go added but please don't break chipTAN on that way. ;)
TAN2Go is not supported anymore by DKB since 23.11.2024. Only pushTAN and chipTAN. Most of us need pushTAN.
Hi, I think I have the same / a related issue when connecting to DKB: I get the error message:
\Python\Python310\lib\site-packages\fints\parser.py:163: FinTSParserWarning: Ignoring parser error and returning generic object: > Wrong input when setting HNVSK3.security_identification_details. Turn off robust_mode to see Exception. warnings.warn("Ignoring parser error and returning generic object: {}. Turn off robust_mode to see Exception.".format(str(e)), FinTSParserWarning)
I am using the (only) accepted security from from DKB (with my account, at least), which is 940/Decoupled
TAN2Go is not supported anymore by DKB since 23.11.2024. Only pushTAN and chipTAN. Most of us need pushTAN.
Apologies! I got the app-based methods mixed up. Corrected that.
Hi, could someone provide a minimal working example? Here is what I have:
from fints.client import FinTS3PinTanClient
from fints.client import FinTS3PinTanClient, NeedTANResponse
from fints.utils import minimal_interactive_cli_bootstrap
logger.info(f"get user / PIN for {bank_and_user}")
bank, account = get_credentials(bank_and_user)
logger.info(f"create")
client = FinTS3PinTanClient(
bank_identifier=bank["BLZ"], # 12030000
user_id=account["user_id"], # Your login name
pin=account["pin"], # Your banking PIN
server=bank["server"],
product_id=FINTS_PRODUCT_ID,
)
logger.info(f"fetch_tan_mechanisms")
client.fetch_tan_mechanisms()
mechanisms = client.get_tan_mechanisms()
mechanisms_map = {m.name: k for k, m in mechanisms.items()}
preference = 'DKB App'
if preference in mechanisms_map.keys():
preferred_id = mechanisms_map.get(preference)
else:
raise Exception(f"meachanism {preference} not offered (options are {mechanisms_map.keys()}")
logger.info(f"set preferred tan machanism {preference}")
client.set_tan_mechanism(preferred_id)
logger.info(f"enter with")
with client:
# Since PSD2, a TAN might be needed for dialog initialization. Let's check if there is one required
if client.init_tan_response:
print("A TAN is required:", client.init_tan_response.challenge)
if not isinstance(client.init_tan_response, NeedTANResponse):
print("No TAN is required")
else:
print("TAN is required")
# else: mobile TAN/manual Smart-TAN/... is used
if client.init_tan_response.decoupled:
tan = input('Please press enter after confirming the transaction in your app:')
else:
tan = input('Please enter TAN:')
transactions = client.send_tan(client.init_tan_response, tan)
else:
logger.info("no tan required")
# just for curiosity
info = client.get_information()
# Fetch accounts
accounts = client.get_sepa_accounts()
logger.info(f"accounts: {accounts}")
logger.info(f"DONE")
and I get this warning:
site-packages\fints\parser.py:163: FinTSParserWarning: Ignoring parser error and returning generic object: Wrong input when setting HNVSK3.security_identification_details. Turn off robust_mode to see Exception.
My App asks me for permission, I give that in mobile phone app and press Enter, but on the python side I get denied
[2025-04-27 00:42:23] ERROR Dialog response: 9050 - Teilweise liegen Fehler vor. [_log_response in client.py:346][fints.client] [2025-04-27 00:42:23] ERROR Dialog response: 9210 - Auftrag abgelehnt [_log_response in client.py:346][fints.client] [2025-04-27 00:42:23] ERROR Dialog response: 9800 - Dialog abgebrochen. [_log_response in client.py:346][fints.client] [2025-04-27 00:42:23] ERROR Dialog response: 9050 - Teilweise liegen Fehler vor. [_log_response in client.py:346][fints.client] [2025-04-27 00:42:23] ERROR Dialog response: 9210 - Auftrag abgelehnt [_log
_response in client.py:346][fints.client]
For some reason, the client.init_tan_response.decoupled is False - I have no idea where to look next. Do I have to enter the app-pin or something?
Hi, could someone provide a minimal working example? Here is what I have:
from fints.client import FinTS3PinTanClient from fints.client import FinTS3PinTanClient, NeedTANResponse from fints.utils import minimal_interactive_cli_bootstrap logger.info(f"get user / PIN for {bank_and_user}") bank, account = get_credentials(bank_and_user) logger.info(f"create") client = FinTS3PinTanClient( bank_identifier=bank["BLZ"], # 12030000 user_id=account["user_id"], # Your login name pin=account["pin"], # Your banking PIN server=bank["server"], product_id=FINTS_PRODUCT_ID, ) logger.info(f"fetch_tan_mechanisms") client.fetch_tan_mechanisms() mechanisms = client.get_tan_mechanisms() mechanisms_map = {m.name: k for k, m in mechanisms.items()} preference = 'DKB App' if preference in mechanisms_map.keys(): preferred_id = mechanisms_map.get(preference) else: raise Exception(f"meachanism {preference} not offered (options are {mechanisms_map.keys()}") logger.info(f"set preferred tan machanism {preference}") client.set_tan_mechanism(preferred_id) logger.info(f"enter with") with client: # Since PSD2, a TAN might be needed for dialog initialization. Let's check if there is one required if client.init_tan_response: print("A TAN is required:", client.init_tan_response.challenge) if not isinstance(client.init_tan_response, NeedTANResponse): print("No TAN is required") else: print("TAN is required") # else: mobile TAN/manual Smart-TAN/... is used if client.init_tan_response.decoupled: tan = input('Please press enter after confirming the transaction in your app:') else: tan = input('Please enter TAN:') transactions = client.send_tan(client.init_tan_response, tan) else: logger.info("no tan required") # just for curiosity info = client.get_information() # Fetch accounts accounts = client.get_sepa_accounts() logger.info(f"accounts: {accounts}") logger.info(f"DONE")and I get this warning:
site-packages\fints\parser.py:163: FinTSParserWarning: Ignoring parser error and returning generic object: Wrong input when setting HNVSK3.security_identification_details. Turn off robust_mode to see Exception.
My App asks me for permission, I give that in mobile phone app and press Enter, but on the python side I get denied
[2025-04-27 00:42:23] ERROR Dialog response: 9050 - Teilweise liegen Fehler vor. [_log_response in client.py:346][fints.client] [2025-04-27 00:42:23] ERROR Dialog response: 9210 - Auftrag abgelehnt [_log_response in client.py:346][fints.client] [2025-04-27 00:42:23] ERROR Dialog response: 9800 - Dialog abgebrochen. [_log_response in client.py:346][fints.client] [2025-04-27 00:42:23] ERROR Dialog response: 9050 - Teilweise liegen Fehler vor. [_log_response in client.py:346][fints.client] [2025-04-27 00:42:23] ERROR Dialog response: 9210 - Auftrag abgelehnt [_log
_response in client.py:346][fints.client]
For some reason, the client.init_tan_response.decoupled is False - I have no idea where to look next. Do I have to enter the app-pin or something?
Hi,
I'm having the same issue. It looks like DKB expects a TAN although the decoupled TAN option is beeing used. I tried to send a 4 or 6 digit dummy TAN but still the same issue. Was somesone confronted with the same problem and found a solution?
HI,
i ran into the same issue using the testscript.py from https://python-fints.readthedocs.io/en/latest/trouble.html with DKB and App-TAN Authentication (940)
The DEBUG output showed it used "2" instead of "S" for the decoupled Authentication. So challenge.decoupled seems not to be set correct.
I got it running cutting back ask_for_tan in the testscript to
def ask_for_tan(response):
return f.send_tan(response,"")
and further hardcoding challenge.decoupled to true in the client.send_tan method
def send_tan(self, challenge: NeedTANResponse, tan: str):
"""
...
"""
challenge.decoupled = True
with self._get_dialog() as dialog:
....
So it seems to me the client does not set challenge.decoupled to true for the 940 method.
I will try to find a clean way patching the source ...
I traced the problem to the following lines in the dialog.py in init(), lines 87ff:
if tan_seg:
for resp in retval.responses(tan_seg):
if resp.code in ('0030', '3955'):
self.client.init_tan_response = NeedTANResponse(
None,
retval.find_segment_first('HITAN'),
'_continue_dialog_initialization',
self.client.is_challenge_structured(),
resp.code == '3955',
)
In my scenario DKB sends me the following Segments
HIRMS:3:2:5+3955::Sicherheitsfreigabe erfolgt über anderen Kanal+0030::Auftrag empfangen - Sicherheitsfreigabe erforderlich'
What happens is that the code first creates a NeedTANResponse with decoupled=True (5th parameter: resp.code == 3955) for the init_tan_response (this is what is needed), but overwrites it in the next loop (matching 0030) with decoupled=False (as resp.code != 3955).
And indeed either limiting the if resp.code statement to if resp.code == 3955 or extending the 5th parameter of the NeedTANRespone to resp.code in ('0030', '3955') both solves the problem for me and the linked test-script above works nice.
I can not really estimate which variant is right, as i have no experience with the FinTS yet. Personally i a actually working with extending resp.code in ('0030', '3955')
Also i would suggest a time.sleep(1) in the client.py after line 1370, so to not spam retrys to the server, and check "only" once in a sec, if the App-Auth worked ?
k... i just realized anyhow i debugged an old code.... the issue is already fixed on current master:
if tan_seg:
for resp in retval.responses(tan_seg):
if resp.code in ('0030', '3955'):
self.client.init_tan_response = NeedTANResponse(
None,
retval.find_segment_first('HITAN'),
'_continue_dialog_initialization',
self.client.is_challenge_structured(),
False,
)
if resp.code == '3955':
self.client.init_tan_response.decoupled = True
break
so no more issues for me...
edit: i just tried the script from @nefarius2001, it also works with the current github code. The latest "fints" Code (4.2.3 from Nov 2024) from PyPi however misses the fix for DKB.
Thanks a lot @jusernrone ! I replaced the pip-installed 4.2.3 release with a submodule-clone of the repo using the current master (3d3644d6c686fdb87769c6ca93786ec4b9f77064). It works!
May I ask a follow-up question: Is there an resonable way to poll (like every second) if the App-Approval has been commited? Asking the user to press enter when being done feels - clumsy (see the line in my script "Please press enter after confirming the transaction in your app:")
It is documented for the send_tan() method:
If the operation was not yet confirmed using the decoupled app, this method will again return a
NeedTANResponse.
So you can loop until it no more returns an instance of it:
from time import sleep
...
looping_for_app_confirmation = False
while isinstance(client.init_tan_response, NeedTANResponse):
if looping_for_app_confirmation == True: sleep(1)
client.init_tan_response = client.send_tan(client.init_tan_response,None)
looping_for_app_confirmation = True
Perhaps it would even make sense to allow send_tan to not require a tan (for these decoupled auth-methods) and add a spam-protection for looping calls?
You are absolutely correct, thanks!
For other travellers: This is my code snippet called with client.init_tan_response and the result from client.get_transactions:
def handle_challenge( client, result_get ): if not isinstance(result_get, NeedTANResponse): logger.debug("No TAN is required") return result_get logger.info("TAN is required") if getattr(result_get, 'challenge_hhduc', None): handle_flicker_terminal() # else: mobile TAN/manual Smart-TAN/... is used while isinstance(result_get, NeedTANResponse): if result_get.decoupled: sleep(1.0) logger.info("poll for decoupled challenge") result_get = client.send_tan(result_get, None) else: tan = input('Please enter TAN:') logger.info("sending TAN") result_get = client.send_tan(result_get, tan)
Request for documentation I'd suggest/request to update the documentation
- Maybe update the "Full example" on the bottom of the page to show such polling instead of the "Please press enter after confirming the transa".. input?
- Maybe provide two examples in "Sending the TAN", one for decoupled and one for standard? I was looking for either of these.
Feedback to @jusernrone
Perhaps it would even make sense to allow send_tan to not require a tan (for these decoupled auth-methods) and add a spam-protection for looping calls?
While I get the reasoning, it feels odd to call a "send_tan" function anyway. I'd intuitively expect a (different) function like client.check_decoupled_auth(). Spam-protection I would as resposibility of the package-user, but it might be a good idea to add a (optional but default-on?) protection just to avoid that the package itself gets negative attention due to people using it inappropriately. Next-level of convenience could be a client.poll_until_decoupled_auth_given() that does the looping behind the scenes.
import logging
from datetime import date
import getpass
from fints.client import FinTS3PinTanClient
from fints.utils import minimal_interactive_cli_bootstrap
import time
from time import sleep
from fints.client import FinTS3PinTanClient, NeedTANResponse
print(" dieses Programm hat am 2025-08-03 funktioniert. man muss aber jedes Mal in der App entsprerren.")
# Enable debug logging for troubleshooting
logging.basicConfig(level=logging.DEBUG)
# DKB connection details
product_id = '6151256F3D4F9975B877BD4A2' # A generic product ID, or you can customize this
# Initialize the FinTS client
client = FinTS3PinTanClient(
bank_identifier= '12030000' ,
user_id= '1111_P',
pin= 'yourpin',
server='https://fints.dkb.de/fints',
product_id='6151256F3D4F9975B877BD4A2',
)
# Make sure this happens BEFORE `with client:`
client.fetch_tan_mechanisms()
mechs = client.get_tan_mechanisms()
client.set_tan_mechanism('940')
with client:
if isinstance(client.init_tan_response, NeedTANResponse):
if client.init_tan_response.decoupled:
print("Waiting for DKB App approval...")
# Poll for app approval
while isinstance(client.init_tan_response, NeedTANResponse):
sleep(1)
client.init_tan_response = client.send_tan(client.init_tan_response, None)
else:
tan = input("Enter TAN: ")
client.send_tan(client.init_tan_response, tan)
# After TAN is resolved:
time.sleep(8)
accounts = client.get_sepa_accounts()
print("\n Account Balances:")
for account in accounts:
try:
balance = client.get_balance(account)
currency = getattr(balance, 'currency', 'EUR')
print(f"- {account.iban} |>> you have so many coins : {balance.amount} {currency}")
except Exception as e:
print(f"- {account.iban} | Failed to fetch balance: {e}")
print("Accounts:", accounts)`