14.2.1.2. Token Class

The following token types are known to edumfa. All are inherited from the base tokenclass describe below.

class edumfa.lib.tokenclass.TokenClass(db_token)[source]

Create a new token object.

Parameters:

db_token (Token) – A database token object

Returns:

A TokenClass object

add_init_details(key, value)[source]

(was addInfo) Adds information to a volatile internal dict

add_tokengroup(tokengroup=None, tokengroup_id=None)[source]

Adds a new tokengroup to this token.

Parameters:
  • tokengroup (basestring) – The name of the token group to add

  • tokengroup_id (int) – The id of the tokengroup to add

Returns:

True

add_tokeninfo(key, value, value_type=None)[source]

Add a key and a value to the DB tokeninfo

Parameters:
  • key

  • value

Returns:

add_user(user, report=None)[source]

Set the user attributes (uid, resolvername, resolvertype) of a token.

Parameters:
  • user – a User() object, consisting of loginname and realm

  • report – tbdf.

Returns:

None

classmethod api_endpoint(request, g)[source]

This provides a function to be plugged into the API endpoint /ttype/<tokentype> which is defined in api/ttype.py

The method should return

return “json”, {}

or

return “text”, “OK”

Parameters:
  • request – The Flask request

  • g – The Flask global object g

Returns:

Flask Response or text

authenticate(passw, user=None, options=None)[source]

High level interface which covers the check_pin and check_otp This is the method that verifies single shot authentication like they are done with push button tokens.

It is a high level interface to support other tokens as well, which do not have a pin and otp separation - they could overwrite this method

If the authentication succeeds an OTP counter needs to be increased, i.e. the OTP value that was used for this authentication is invalidated!

Parameters:
  • passw (string) – the password which could be pin+otp value

  • user (User object) – The authenticating user

  • options (dict) – dictionary of additional request parameters

Returns:

returns tuple of

  1. true or false for the pin match,

  2. the otpcounter (int) and the

  3. reply (dict) that will be added as additional information in

    the JSON response of /validate/check.

Return type:

tuple(bool, int, dict)

can_verify_enrollment = False
static challenge_janitor()[source]

Just clean up all challenges, for which the expiration has expired.

Returns:

None

check_all(message_list)[source]

Perform all checks on the token. Returns False if the token is either: * auth counter exceeded * not active * fail counter exceeded * validity period exceeded

This is used in the function token.check_token_list

Parameters:

message_list – A list of messages

Returns:

False, if any of the checks fail

check_auth_counter()[source]

This function checks the count_auth and the count_auth_success. If the counters are less or equal than the maximum allowed counters it returns True. Otherwise False.

Returns:

success if the counter is less than max

Return type:

bool

check_challenge_response(user=None, passw=None, options=None)[source]

This method verifies if there is a matching challenge for the given passw and also verifies if the response is correct.

It then returns the new otp_counter of the token.

In case of success the otp_counter will be >= 0.

Parameters:
  • user (User object) – the requesting user

  • passw (string) – the password (pin+otp)

  • options (dict) – additional arguments from the request, which could be token specific. Usually “transactionid”

Returns:

return otp_counter. If -1, challenge does not match

Return type:

int

check_failcount()[source]

Checks if the failcounter is exceeded. It returns True, if the failcounter is less than maxfail

Returns:

True or False

Return type:

bool

check_last_auth_newer(last_auth)[source]

Check if the last successful authentication with the token is newer than the specified time delta which is passed as 10h, 7d or 1y.

It returns True, if the last authentication with this token is newer than the specified delta or by any chance exactly the same.

It returns False, if the last authentication is older or if the data in the token can not be parsed.

Parameters:

last_auth (basestring) – 10h, 7d or 1y

Returns:

bool

check_otp(otpval, counter=None, window=None, options=None)[source]

This checks the OTP value, AFTER the upper level did the checkPIN

In the base class we do not know, how to calculate the OTP value. So we return -1. In case of success, we should return >=0, the counter

Parameters:
  • otpval – the OTP value

  • counter (int) – The counter for counter based otp values

  • window – a counter window

  • options (dict) – additional token specific options

Returns:

counter of the matching OTP value.

Return type:

int

check_otp_exist(otp, window=None)[source]

checks if the given OTP value is/are values of this very token. This is used to autoassign and to determine the serial number of a token.

Parameters:
  • otp – the OTP value

  • window (int) – The look ahead window

Returns:

True or a value > 0 in case of success

check_pin(pin, user=None, options=None)[source]

Check the PIN of the given Password. Usually this is only dependent on the token itself, but the user object can cause certain policies.

Each token could implement its own PIN checking behaviour.

Parameters:
  • pin (string) – the PIN (static password component), that is to be checked.

  • user (User object) – for certain PIN policies (e.g. checking against the user store) this is the user, whose password would be checked. But at the moment we are checking against the userstore in the decorator “auth_otppin”.

  • options – the optional request parameters

Returns:

If the PIN is correct, return True

Return type:

bool

check_reset_failcount()[source]

Checks if we should reset the failcounter due to the FAILCOUNTER_CLEAR_TIMEOUT

Returns:

True, if the failcounter was reset

check_validity_period()[source]

This checks if the datetime.now() is within the validity period of the token.

Returns:

success

Return type:

bool

client_mode = 'interactive'
create_challenge(transactionid=None, options=None)[source]

This method creates a challenge, which is submitted to the user. The submitted challenge will be preserved in the challenge database.

If no transaction id is given, the system will create a transaction id and return it, so that the response can refer to this transaction.

Parameters:
  • transactionid – the id of this challenge

  • options (dict) – the request context parameters / data

Returns:

tuple of (bool, message, transactionid, reply_dict)

Return type:

tuple

The return tuple builds up like this: bool if submit was successful; message which is displayed in the JSON response; additional challenge reply_dict, which are displayed in the JSON challenges response.

static decode_otpkey(otpkey, otpkeyformat)[source]

Decode the otp key which is given in a specific format.

Supported formats:
  • hex, in which the otpkey is returned verbatim

  • base32check, which is specified in decode_base32check

In case the OTP key is malformed or if the format is unknown, a ParameterError is raised.

Parameters:
  • otpkey – OTP key passed by the user

  • otpkeyformat – “hex” or “base32check”

Returns:

hex-encoded otpkey

del_tokengroup(tokengroup=None, tokengroup_id=None)[source]

Removes a token group from a token. You either need to specify the name or the ID of the tokengroup.

Parameters:
  • tokengroup (basestring) – The name of the tokengroup

  • tokengroup_id (int) – The ID of the tokengroup

Returns:

True in case of success

del_tokeninfo(key=None)[source]
delete_token()[source]

delete the database token

enable(enable=True)[source]
classmethod enroll_via_validate(g, content, user_obj)[source]

This class method is used in the policy ENROLL_VIA_MULTICHALLENGE. It enrolls a new token of this type and returns the necessary information to the client by modifying the content.

Parameters:
  • g – context object

  • content – The content of a response

  • user_obj – A user object

Returns:

None, the content is modified

enroll_via_validate_2nd_step(passw, options=None)[source]

This method is the optional second step of ENROLL_VIA_MULTICHALLENGE. It is used in situations like the email token, sms token or push, when enrollment via challenge response needs two steps.

Parameters:

options

Returns:

generate_symmetric_key(server_component, client_component, options=None)[source]

This method generates a symmetric key, from a server component and a client component. This key generation could be based on HMAC, KDF or even Diffie-Hellman.

The basic key-generation is simply replacing the last n byte of the server component with bytes of the client component.

Parameters:
  • server_component (str) – The component usually generated by privacyIDEA. This is a hex string

  • client_component (str) – The component usually generated by the client (e.g. smartphone). This is a hex string.

  • options

Returns:

the new generated key as hex string

Return type:

str

get_as_dict()[source]

This returns the token data as a dictionary. It is used to display the token list at /token/list.

Returns:

The token data as dict

Return type:

dict

static get_class_info(key=None, ret='all')[source]
static get_class_prefix()[source]
static get_class_type()[source]
get_count_auth()[source]

Return the number of all authentication tries

get_count_auth_max()[source]

Return the number of maximum allowed authentications

get_count_auth_success()[source]

Return the number of successful authentications

get_count_auth_success_max()[source]

Return the maximum allowed successful authentications

get_count_window()[source]
classmethod get_default_settings(g, params)[source]

This method returns a dictionary with default settings for token enrollment. These default settings depend on the token type and the defined policies.

The returned dictionary is added to the parameters of the API call.

Parameters:
  • g – context object, see documentation of Match

  • params (dict) – The call parameters

Returns:

default parameters

get_failcount()[source]
static get_hashlib(hLibStr)[source]

Returns a hashlib function for a given string

Parameters:

hLibStr (string) – the hashlib

Returns:

the hashlib

Return type:

function

static get_import_csv(l)[source]

Read the list from a csv file and return a dictionary, that can be used to do a token_init.

Parameters:

l (list) – The list of the line of a csv file

Returns:

A dictionary of init params

get_init_detail(params=None, user=None)[source]

to complete the token initialization, the response of the initialization should be build by this token specific method. This method is called from api/token after the token is enrolled

get_init_detail returns additional information after an admin/init like the QR code of an HOTP/TOTP token. Can be anything else.

Parameters:
  • params (dict) – The request params during token creation token/init

  • user (User object) – the user, token owner

Returns:

additional descriptions

Return type:

dict

get_init_details()[source]

return the status of the token rollout

Returns:

return the status dict.

Return type:

dict

get_max_failcount()[source]
get_multi_otp(count=0, epoch_start=0, epoch_end=0, curTime=None, timestamp=None)[source]

This returns a dictionary of multiple future OTP values of a token.

Parameters:
  • count – how many otp values should be returned

  • epoch_start – time based tokens: start when

  • epoch_end – time based tokens: stop when

  • curTime (datetime object) – current time for TOTP token (for selftest)

  • timestamp (int) – unix time, current time for TOTP token (for selftest)

Returns:

True/False, error text, OTP dictionary

Return type:

Tuple

get_otp(current_time='')[source]

The default token does not support getting the otp value will return a tuple of four values a negative value is a failure.

Returns:

something like: (1, pin, otpval, combined)

get_otp_count()[source]
get_otp_count_window()[source]
get_otplen()[source]
get_pin_hash_seed()[source]
get_realms()[source]

Return a list of realms the token is assigned to

Returns:

realms

Return type:

list

get_serial()[source]
static get_setting_type(key)[source]

This function returns the type of the token specific config/setting. This way a tokenclass can define settings, that can be “public” or a “password”. If this setting is written to the database, the type of the setting is set automatically in set_edumfa_config

The key name needs to start with the token type.

Parameters:

key – The token specific setting key

Returns:

A string like “public”

get_sync_window()[source]
get_tokeninfo(key=None, default=None)[source]

return the complete token info or a single key of the tokeninfo. When returning the complete token info dictionary encrypted entries are not decrypted. If you want to receive a decrypted value, you need to call it directly with the key.

Parameters:
  • key (string) – the key to return

  • default (string) – the default value, if the key does not exist

Returns:

the value for the key

Return type:

int or str or dict

get_tokentype()[source]
get_type()[source]
get_user_displayname()[source]

Returns a tuple of a user identifier like user@realm and the displayname of “givenname surname”.

Returns:

tuple

get_user_id()[source]
get_validity_period_end()[source]

returns the end of validity period (if set) if not set, “” is returned.

Returns:

the end of the validity period

Return type:

str

get_validity_period_start()[source]

returns the start of validity period (if set) if not set, “” is returned.

Returns:

the start of the validity period

Return type:

str

hKeyRequired = False
has_db_challenge_response(passw, user=None, options=None)[source]

This method checks, if the given transaction_id is actually the response to a real challenge. To do so, it verifies, if there is a DB entry for the given serial number and transaction_id. This is to avoid side effects by passing non-existent transaction_ids.

This method checks, if the token still has a challenge

Parameters:
  • passw

  • user

  • options

Returns:

has_further_challenge(options=None)[source]

Returns true, if a token requires more than one challenge during challenge response authentication. This could be a 4eyes token or indexed secret token, that queries more than on input.

Parameters:

options – Additional options from the request

Returns:

True, if this very token requires further challenges

inc_count_auth()[source]

Increase the counter, that counts authentications - successful and unsuccessful

inc_count_auth_success()[source]

Increase the counter, that counts successful authentications Also increase the auth counter

inc_failcount()[source]
inc_otp_counter(counter=None, increment=1, reset=True)[source]

Increase the otp counter and store the token in the database

Before increasing the token.count the token.count can be set using the parameter counter.

Parameters:
  • counter (int) – if given, the token counter is first set to counter and then increased by increment

  • increment (int) – increase the counter by this amount

  • reset (bool) – reset the failcounter if set to True

Returns:

the new counter value

is_active()[source]
is_challenge_request(passw, user=None, options=None)[source]

This method checks, if this is a request, that triggers a challenge.

The default behaviour to trigger a challenge is, if the passw parameter only contains the correct token pin and the request contains a data or a challenge key i.e. if the options parameter contains a key data or challenge.

Each token type can decide on its own under which condition a challenge is triggered by overwriting this method.

Note

in case of pin policy == 2 (no pin is required) the check_pin would always return true! Thus each request containing a data or challenge would trigger a challenge!

The Challenge workflow is like this.

When an authentication request is issued, first it is checked if this is a request which will create a new challenge (is_challenge_request) or if this is a response to an existing challenge (is_challenge_response). In these two cases during request processing the following functions are called:

is_challenge_request or is_challenge_response  <-------+
         |                       |                     |
         V                       V                     |
create_challenge        check_challenge_response     create_challenge
         |                       |                     ^
         |                       |                     |
         |              has_further_challenge [yes] ---+
         |                      [no]
         |                       |
         V                       V
challenge_janitor       challenge_janitor
Parameters:
  • passw (string) – password, which might be pin or pin+otp

  • user (User object) – The user from the authentication request

  • options (dict) – dictionary of additional request parameters

Returns:

true or false

Return type:

bool

is_challenge_response(passw, user=None, options=None)[source]

This method checks, if this is a request that is supposed to be the answer to a previous challenge.

The default behaviour to check if this is the response to a previous challenge is simply by checking if the request contains a parameter state or transactionid i.e. checking if the options parameter contains a key state or transactionid.

This method does not try to verify the response itself! It only determines, if this is a response for a challenge or not. If the challenge still exists, is checked in has_db_challenge_response. The response is verified in check_challenge_response.

Parameters:
  • passw (string) – password, which might be pin or pin+otp

  • user (User object) – the requesting user

  • options (dict) – dictionary of additional request parameters

Returns:

true or false

Return type:

bool

is_fit_for_challenge(messages, options=None)[source]

This method is called if a cryptographically matching response to a challenge was found. This method may implement final checks, if there is anything that should deny the success of the authentication with the response to the challenge.

The options dictionary can also contain the transaction_id, so even the challenge table for this token can be used for checking.

Parameters:
  • options (dict)

  • messages (list) – This is a list of messages. This method can append new information to this message list.

Returns:

True or False

is_locked()[source]

Check if the token is in a locked state A locked token can not be modified

Returns:

True, if the token is locked.

is_multichallenge_enrollable = False
is_orphaned()[source]

Return True if the token is orphaned.

An orphaned token means, that it has a user assigned, but the user does not exist in the user store (anymore)

Returns:

True / False

Return type:

bool

classmethod is_outofband()[source]
is_pin_change(password=False)[source]

Returns true if the pin of the token needs to be changed.

Parameters:

password (bool) – Whether the password needs to be changed.

Returns:

True or False

is_previous_otp(otp, window=10)[source]

checks if a given OTP value is a previous OTP value, that lies in the past or has a lower counter.

This is used in case of a failed authentication to return the information, that this OTP values was used previously and is invalid.

Parameters:
  • otp (basestring) – The OTP value.

  • window (int) – A counter window, how far we should look into the past.

Returns:

bool

is_revoked()[source]

Check if the token is in the revoked state

Returns:

True, if the token is revoked

mode = ['authenticate', 'challenge']
post_success()[source]

Run anything after a token was used for successful authentication

prepare_verify_enrollment()[source]

This is called, if the token should be enrolled in a way, that the user needs to provide a proof, that the server can verify, that the token was successfully enrolled. E.g. with HOTP tokens the user might need to provide a correct OTP value.

The returned dictionary is added to the response in “detail” -> “verify”.

Returns:

A dictionary with information that is needed to trigger the verification.

reset()[source]

Reset the failcounter

resync(otp1, otp2, options=None)[source]
revoke()[source]

This revokes the token. By default it 1. sets the revoked-field 2. set the locked field 3. disables the token.

Some token types may revoke a token without locking it.

property rollout_state
save()[source]

Save the database token

set_count_auth(count)[source]

Sets the counter for the occurred login attepms as key “count_auth” in token info

Parameters:

count (int) – a number

set_count_auth_max(count)[source]

Sets the counter for the maximum allowed login attempts as key “count_auth_max” in token info

Parameters:

count (int) – a number

set_count_auth_success(count)[source]

Sets the counter for the occurred successful logins as key “count_auth_success” in token info

Parameters:

count (int) – a number

set_count_auth_success_max(count)[source]

Sets the counter for the maximum allowed successful logins as key “count_auth_success_max” in token info

Parameters:

count (int) – a number

set_count_window(countWindow)[source]
set_defaults()[source]

Set the default values on the database level

set_description(description)[source]

Set the description on the database level

Parameters:

description (string) – description of the token

set_failcount(failcount)[source]

Set the failcounter in the database

set_hashlib(hashlib)[source]
set_init_details(details)[source]
set_maxfail(maxFail)[source]
set_next_pin_change(diff=None, password=False)[source]

Sets the timestamp for the next_pin_change. Provide a difference like 90d (90 days).

Parameters:
  • diff (basestring) – The time delta.

  • password – Do no set next_pin_change but next_password_change

Returns:

None

set_otp_count(otpCount)[source]
set_otpkey(otpKey)[source]
set_otplen(otplen)[source]
set_pin(pin, encrypt=False)[source]

set the PIN of a token. Usually the pin is stored in a hashed way.

Parameters:
  • pin (basestring) – the pin to be set for the token

  • encrypt (bool) – If set to True, the pin is stored encrypted and can be retrieved from the database again

set_pin_hash_seed(pinhash, seed)[source]
set_realms(realms, add=False)[source]

Set the list of the realms of a token.

Parameters:
  • realms (list) – realms the token should be assigned to

  • add (boolean) – if the realms should be added and not replaced

set_so_pin(soPin)[source]
set_sync_window(syncWindow)[source]
set_tokengroups(tokengroups, add=False)[source]

Set the list of the tokengroups of a token.

Parameters:
  • tokengroups (list) – realms the token should be assigned to

  • add (boolean) – if the tokengroups should be added and not replaced

set_tokeninfo(info)[source]

Set the tokeninfo field in the DB. Old values will be deleted.

Parameters:

info (dict) – dictionary with key and value

Returns:

set_type(tokentype)[source]

Set the tokentype in this object and also in the underlying database-Token-object.

Parameters:

tokentype (string) – The type of the token like HOTP or TOTP

set_user_pin(userPin)[source]
set_validity_period_end(end_date)[source]

sets the end date of the validity period for a token

Parameters:

end_date (str) – the end date in the format YYYY-MM-DDTHH:MM+OOOO if the format is wrong, the method will throw an exception

set_validity_period_start(start_date)[source]

sets the start date of the validity period for a token

Parameters:

start_date (str) – the start date in the format YYYY-MM-DDTHH:MM+OOOO if the format is wrong, the method will throw an exception

split_pin_pass(passw, user=None, options=None)[source]

Split the password into the token PIN and the OTP value

take the given password and split it into the PIN and the OTP value. The splitting can be dependent of certain policies. The policies may depend on the user.

Each token type may define its own way to slit the PIN and the OTP value.

Parameters:
  • passw – the password to split

  • user (User object) – The user/owner of the token

  • options (dict) – can be used be the token types.

Returns:

tuple of pin and otp value

Returns:

tuple of (split status, pin, otp value)

Return type:

tuple

status_validation_fail()[source]

callback to enable a status change, if auth failed

status_validation_success()[source]

callback to enable a status change, if auth succeeds

static test_config(params=None)[source]

This method is used to test the token config. Some tokens require some special token configuration like the SMS-Token or the Email-Token. To test this configuration, this classmethod is used.

It takes token specific parameters and returns a tuple of a boolean and a result description.

Parameters:

params (dict) – token specific parameters

Returns:

success, description

Return type:

tuple

update(param, reset_failcount=True)[source]

Update the token object

Parameters:

param – a dictionary with different params like keysize, description, genkey, otpkey, pin

Type:

param: dict

use_for_authentication(options)[source]

This method checks, if this token should be used for authentication. Certain token classes could be excluded from the authentication request in certain situations.

Returns True, if the token should be used for authentication. Returns False, if the token should be completely ignored for authentication.

Parameters:

options – This is the option list, that basically contains the Request parameters.

Returns:

property user

return the user (owner) of a token If the token has no owner assigned, we return None

Returns:

The owner of the token

Return type:

User object or None

using_pin = True
verify_enrollment(response)[source]

This is called during the 2nd step of the verified enrollment. This method verifies the actual response from the user. Returns true, if the verification was successful.

Parameters:

response – The response given by the user

Returns:

True