Working with TANs¶
Many operations in FinTS will require a form of two-step authentication, called TANs. TANs are mostly required for operations that move money or change details of a bank account. TANs can be generated with a multitude of methods, including paper lists, smartcard readers, SMS messages, and smartphone apps.
TAN methods¶
Before doing any operations involving TANs, you should get a list of supported TAN mechanisms:
mechanisms = client.get_tan_mechanisms()
The returned dictionary maps identifiers (generally: three-digit numerals) to instances of a
TwoStepParametersCommon()
subclass with varying fields, depending on the
version of the two-step process and the bank.
The name field of these objects provides a user-friendly name of the TAN mechanism that you
can display to the user to choose from. To select a TAN mechanism, you can use
set_tan_mechanism()
, which takes the identifier used as
key in the get_tan_mechanisms()
return value.
If the description_required
attribute for the TAN mechanism is MUST
,
you will need to get a list of TAN media with get_tan_media()
and select the
appropriate one with set_tan_medium()
.
Have a look at the source code of minimal_interactive_cli_bootstrap()
for an example on how to
ask the user for these properties.
You may not change the active TAN mechanism or TAN medium within a standing dialog (see Storing and restoring dialog state).
The selection of the active TAN mechanism/medium is stored with the persistent client data (see Storing and restoring client state).
-
class
fints.client.
FinTS3PinTanClient
(bank_identifier, user_id, pin, server, customer_id=None, *args, **kwargs)[source] -
get_current_tan_mechanism
()[source]
-
get_tan_mechanisms
()[source] Get the available TAN mechanisms.
Note: Only checks for HITANS versions listed in IMPLEMENTED_HKTAN_VERSIONS.
Returns: Dictionary of security_function: TwoStepParameters objects.
-
get_tan_media
(media_type=fints.formals.TANMediaType2.ALL, media_class=fints.formals.TANMediaClass4.ALL)[source] Get information about TAN lists/generators.
Returns tuple of fints.formals.TANUsageOption and a list of fints.formals.TANMedia4 or fints.formals.TANMedia5 objects.
-
set_tan_mechanism
(security_function)[source]
-
set_tan_medium
(tan_medium)[source]
-
TAN challenges¶
When you try to perform an operation that requires a TAN to proceed, you will receive an object containing the bank’s challenge (and some internal data to continue the operation once the TAN has been processed):
-
class
fints.client.
NeedTANResponse
(command_seg, tan_request, resume_method=None, tan_request_structured=False)[source]¶ -
challenge
= None¶ Textual challenge to be displayed to the user
-
challenge_hhduc
= None¶ HHD_UC challenge to be transmitted to the TAN generator
-
challenge_html
= None¶ HTML-safe challenge text, possibly with formatting
-
challenge_matrix
= None¶ Matrix code challenge: tuple(mime_type, data)
-
challenge_raw
= None¶ Raw challenge as received by the bank
-
get_data
() → bytes[source]¶ Return a compressed datablob representing this object.
To restore the object, use
fints.client.NeedRetryResponse.from_data()
.
-
The challenge
attribute will contain human-readable instructions on how to proceed.
The challenge_html
attribute will possibly contain a nicer, formatted, HTML version of the challenge text
that you should prefer if your primary interface can render HTML. The contents are guaranteed to be proper and
clean (by using the bleach library): They can be used with mark_safe in Django.
The challenge_hhduc
attribute will contain the challenge to be used with a TAN generator device using the
Hand Held Device Unidirectional Coupling specification (such as a Flicker-Code).
Flicker-Code / optiTAN¶
If you want to use chipTAN with an optical TAN device, we provide utilities to print the flicker code on
a unix terminal. Just pass the challenge_hhd_uc
value to this method:
-
fints.hhd.flicker.
terminal_flicker_unix
(code, field_width=3, space_width=3, height=1, clear=False, wait=0.05)[source]¶ Re-encodes a flicker code and prints it on a unix terminal.
Parameters: - code – Challenge value
- field_width – Width of fields in characters (default: 3).
- space_width – Width of spaces in characters (default: 3).
- height – Height of fields in characters (default: 1).
- clear – Clear terminal after every line (default:
False
). - wait – Waiting interval between lines (default: 0.05).
You should probably catch for KeyboardInterrupts
to allow the user to abort the displaying and to continue
with the TAN:
try:
terminal_flicker_unix(result.challenge_hhduc)
except KeyboardInterrupt:
pass
photoTAN¶
If you want to use photoTAN, use the challenge_matrix
attribute to access the image file, e.g. by writing it to
a file:
with open("tan.png", "wb") as writer:
writer.write(result.challenge_matrix[1])
writer.close()
Sending the TAN¶
Once obtained the TAN, you can send it with the send_tan
client method:
-
class
fints.client.
FinTS3PinTanClient
(bank_identifier, user_id, pin, server, customer_id=None, *args, **kwargs)[source] -
send_tan
(challenge: fints.client.NeedTANResponse, tan: str)[source] Sends a TAN to confirm a pending operation.
Parameters: - challenge – NeedTANResponse to respond to
- tan – TAN value
Returns: Currently no response
-
For example:
tan = input('Please enter the TAN code: ')
result = client.send_tan(result, tan)
Storing and restoring TAN state¶
The get_data()
method and
from_data()
factory method can be used to store and restore
a TAN state object between steps.
-
class
fints.client.
NeedRetryResponse
[source]¶ Base class for Responses that need the operation to be externally retried.
A concrete subclass of this class is returned, if an operation cannot be completed and needs a retry/completion. Typical (and only) example: Requiring a TAN to be provided.
You SHOULD use this facility together with the client and dialog state restoration facilities:
client = FinTS3PinTanClient(...)
# Optionally: choose a tan mechanism with
# client.set_tan_mechanism(…)
with client:
response = client.sepa_transfer(...)
dialog_data = client.pause_dialog()
client_data = client.deconstruct()
tan_data = response.get_data()
tan_request = NeedRetryResponse.from_data(tan_data)
print("TAN request: {}".format(tan_request.challenge))
tan = input('Enter TAN: ')
tan_request = NeedRetryResponse.from_data(tan_data)
client = FinTS3PinTanClient(..., from_data=client_data)
with client.resume_dialog(dialog_data):
response = client.send_tan(tan_request, tan)
print(response.status)
print(response.responses)
Reference¶
-
class
fints.formals.
TwoStepParameters2
(*args, **kwargs)[source] -
name
Name des Zwei-Schritt-Verfahrens
Type: str
-
max_length_input
Maximale Länge des Eingabewertes im Zwei-Schritt-Verfahren
Type: int
-
allowed_format
Erlaubtes Format im Zwei-Schritt-Verfahren
Type: fints.formals.AllowedFormat
-
text_return_value
Text zur Belegung des Rückgabewertes im Zwei-Schritt-Verfahren
Type: str
-
max_length_return_value
Maximale Länge des Rückgabewertes im Zwei-Schritt-Verfahren
Type: int
-
number_of_supported_lists
Anzahl unterstützter aktiver TAN-Listen
Type: int
-
multiple_tans_allowed
Mehrfach-TAN erlaubt
Type: bool
-
tan_time_dialog_association
TAN Zeit- und Dialogbezug
Type: fints.formals.TANTimeDialogAssociation
-
tan_list_number_required
TAN-Listennummer erforderlich
Type: fints.formals.TANListNumberRequired
-
cancel_allowed
Auftragsstorno erlaubt
Type: bool
-
challenge_class_required
Challenge-Klasse erforderlich
Type: bool
-
challenge_value_required
Challenge-Betrag erforderlich
Type: bool
-
VERSION
TAN mechanism version
-
-
class
fints.formals.
TwoStepParameters3
(*args, **kwargs)[source] -
name
Name des Zwei-Schritt-Verfahrens
Type: str
-
max_length_input
Maximale Länge des Eingabewertes im Zwei-Schritt-Verfahren
Type: int
-
allowed_format
Erlaubtes Format im Zwei-Schritt-Verfahren
Type: fints.formals.AllowedFormat
-
text_return_value
Text zur Belegung des Rückgabewertes im Zwei-Schritt-Verfahren
Type: str
-
max_length_return_value
Maximale Länge des Rückgabewertes im Zwei-Schritt-Verfahren
Type: int
-
number_of_supported_lists
Anzahl unterstützter aktiver TAN-Listen
Type: int
-
multiple_tans_allowed
Mehrfach-TAN erlaubt
Type: bool
-
tan_time_dialog_association
TAN Zeit- und Dialogbezug
Type: fints.formals.TANTimeDialogAssociation
-
tan_list_number_required
TAN-Listennummer erforderlich
Type: fints.formals.TANListNumberRequired
-
cancel_allowed
Auftragsstorno erlaubt
Type: bool
-
challenge_class_required
Challenge-Klasse erforderlich
Type: bool
-
challenge_value_required
Challenge-Betrag erforderlich
Type: bool
-
initialization_mode
Initialisierungsmodus
Type: fints.formals.InitializationMode
-
description_required
Bezeichnung des TAN-Medium erforderlich
Type: fints.formals.DescriptionRequired
-
supported_media_number
Anzahl unterstützter aktiver TAN-Medien
Type: int
-
VERSION
TAN mechanism version
-
-
class
fints.formals.
TwoStepParameters5
(*args, **kwargs)[source] -
zka_id
ZKA TAN-Verfahren
Type: str
-
zka_version
Version ZKA TAN-Verfahren
Type: str
-
name
Name des Zwei-Schritt-Verfahrens
Type: str
-
max_length_input
Maximale Länge des Eingabewertes im Zwei-Schritt-Verfahren
Type: int
-
allowed_format
Erlaubtes Format im Zwei-Schritt-Verfahren
Type: fints.formals.AllowedFormat
-
text_return_value
Text zur Belegung des Rückgabewertes im Zwei-Schritt-Verfahren
Type: str
-
max_length_return_value
Maximale Länge des Rückgabewertes im Zwei-Schritt-Verfahren
Type: int
-
number_of_supported_lists
Anzahl unterstützter aktiver TAN-Listen
Type: int
-
multiple_tans_allowed
Mehrfach-TAN erlaubt
Type: bool
-
tan_time_dialog_association
TAN Zeit- und Dialogbezug
Type: fints.formals.TANTimeDialogAssociation
-
tan_list_number_required
TAN-Listennummer erforderlich
Type: fints.formals.TANListNumberRequired
-
cancel_allowed
Auftragsstorno erlaubt
Type: bool
-
sms_charge_account_required
SMS-Abbuchungskonto erforderlich
Type: fints.formals.SMSChargeAccountRequired
-
principal_account_required
Auftraggeberkonto erforderlich
Type: fints.formals.PrincipalAccountRequired
-
challenge_class_required
Challenge-Klasse erforderlich
Type: bool
-
challenge_structured
Challenge strukturiert
Type: bool
-
initialization_mode
Initialisierungsmodus
Type: fints.formals.InitializationMode
-
description_required
Bezeichnung des TAN-Medium erforderlich
Type: fints.formals.DescriptionRequired
-
supported_media_number
Anzahl unterstützter aktiver TAN-Medien
Type: int
-
VERSION
TAN mechanism version
-