6.1.1.3.2.30. linotp.lib.tokenclass module¶
This file containes the standard token definitions: - OCRATokenClass
It also contains the base class “TokenClass”, that you may use to define your own tokenclasses.
You can add your own Tokens by adding the modules comma seperated to the directive ‘linotpTokenModules’ in the linotp.ini file.
depends on several modules from linotp.lib but also in case of VascoTokenClass on linotp.lib.ImportOTP.vasco
- class linotp.lib.tokenclass.OcraTokenClass(aToken)[source]¶
Bases: linotp.lib.tokenclass.TokenClass
OcraTokenClass implement an ocra compliant token
- used from Config
- OcraMaxChallenges - number of open challenges per token if None: 3 OcraChallengeTimeout - timeout definition like 1D, 2H or 3M if None: 1M OcraDefaultSuite - if none :’OCRA-1:HOTP-SHA256-8:C-QN08’ QrOcraDefaultSuite - if none :’OCRA-1:HOTP-SHA256-8:C-QA64’
algorithm Ocra Token Rollout: tow phases of rollout
- https://linotpserver/admin/init?
type=ocra& genkey=1& sharedsecret=1& user=BENUTZERNAME& session=SESSIONKEY
=>> “serial” : SERIENNUMMER, “sharedsecret” : DATAOBJECT, “app_import” : IMPORTURL - genSharedSecret - vom HSM oder urandom ? - app_import : + linotp://
- ocrasuite ->> default aus dem config: (DefaultOcraSuite)
- sharedsecret (Länge wie ???)
- seriennummer
- seriennummer: uuid
- token wird angelegt ist aber nicht aktiv!!! (counter == 0)
- https://linotpserver/admin/init?
type=ocra& genkey=1& activationcode=AKTIVIERUNGSCODE& user=BENUTZERNAME& message=MESSAGE& session=SESSIONKEY
=>> “serial” : SERIENNUMMER, “nonce” : DATAOBJECT, “transactionid” : “TRANSAKTIONSID, “app_import” : IMPORTURL
- nonce - von HSM oder random ?
- pkcs5 - kdf2
- es darf zur einer Zeit nur eine QR Token inaktiv (== im Ausrollzustand) sein !!!!! der Token wird über den User gefunden
- seed = pdkdf2(nonce + activcode + shared secret)
- challenge generiern - von urandom oder HSM
- check_t
- counter ist > nach der ersten Transaktion
- if counter >= 1: delete sharedsecret löschen
- autosync(ocraSuite, passw, challenge)[source]¶
try to resync a token automaticaly, if a former and the current request failed
Parameters: - ocraSuite (ocra object) – the ocraSuite of the current Token
- passw –
- challenge(data, session='', typ='raw', challenge=None)[source]¶
the challenge method is for creating an transaction / challenge object
remark: the transaction has a maximum lifetime and a reference to the OcraSuite token (serial)
Parameters: - data (string or None) – data, which is the base for the challenge or None
- session (string) – session support for ocratokens
Returns: challenge response containing the transcation id and the challenge for the ocrasuite
:rtype : tuple of (transId(string), challenge(string))
- checkOtp(passw, counter, window, options=None)[source]¶
checkOtp - standard callback of linotp to verify the token
Parameters: - passw (string) – the passw / otp, which has to be checked
- counter (int) – the start counter
- window (int) – the window, in which the token is valid
- options (dict) – options contains the transaction id, eg. if check_t checks one transaction this will support assynchreonous otp checks (when check_t is used)
Returns: verification counter or -1
Return type: int (-1)
- classmethod getClassType()[source]¶
getClassType - return the token type shortname
Returns: ‘ocra’ Return type: string
- getInfo()[source]¶
getInfo - return the status of the token rollout
Returns: info of the ocra token state Return type: dict
- getInitDetail(params, user=None)[source]¶
to complete the token normalisation, the response of the initialiastion should be build by the token specific method, the getInitDetails
- getOcraSuiteSuite()[source]¶
getQROcraSuiteSuite - return the QR Ocra Suite - if none, it will return the default
Returns: Ocrasuite of token Return type: string
- getQROcraSuiteSuite()[source]¶
getQROcraSuiteSuite - return the QR Ocra Suite - if none, it will return the default
Returns: QROcrasuite of token Return type: string
- getStatus(transactionId)[source]¶
getStatus - assembles the status of a transaction / challenge in a dict
- { “serial”: SERIENNUMMER1,
- “transactionid”: TRANSACTIONID1, “received_tan”: true, “valid_tan”: true, “failcount”: 0
}
Parameters: transactionId (string) – the transaction / challenge id Returns: status dict Return type: dict
- classmethod getTransaction(transId)[source]¶
getTransaction - lookup for the challenge object of the given id
Parameters: transId (string) – challenge identifier Returns: the challenge data object Return type: OcraChallenge
- classmethod getTransactions4serial(serial, currentOnly=False)[source]¶
getTransactions4serial - give all challenges for a given token serial number
Parameters: - serial (string) – token serial identifier
- currentOnly (boolean flag) – boolean Flag to return all Challenges (like for status request) or to return the eldest open transaction / challenge
Returns: return a list of Challenges
Return type: OcraChallenge obejct list
- is_challenge_response(passw, user, options=None, challenges=None)[source]¶
check, if the request contains the result of a challenge
Parameters: - passw – password, which might be pin or pin+otp
- user – the requesting user
- options – dictionary of additional request parameters
Returns: returns true or false
- classmethod maxChallengeJanitor(transId=None, serial=None)[source]¶
maxChallengeJanitor - remove for one token (serial) all challengens but the last ones
Parameters: - transId (string) – the current transaction, which provides a the lookup for the serial number
- serial (string) – the serial number of the token
Returns: - nothing
- classmethod maxChallengeRequestJanitor()[source]¶
maxChallengeRequestJanitor - remove all transactions / challenges which have been made more than maxChallengeRequests
Returns: - nothing
- resync(otp1, otp2, options=None)[source]¶
- for the resync to work, we take the last two transactions and their challenges
- for each challenge, we search forward the sync window length
- signData(data)[source]¶
sign the received data with the secret key
Parameters: data – arbitrary string object Returns: hexlified signature of the data
- statusValidationFail()[source]¶
statusValidationFail - callback to enable a status change,
will be called if the token verification has failed
:return - nothing
- statusValidationSuccess()[source]¶
statusValidationSuccess - callback to enable a status change,
remark: will be called if the token shas been succesfull verified
Returns: - nothing
- class linotp.lib.tokenclass.TokenClass(token)[source]¶
Bases: object
- authenticate(passw, user, options=None)[source]¶
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 as well other tokens, which do not have a pin and otp seperation - they could overwrite this method
remarks: we have to call the global methods (check_pin,++) as they take the pin policies into account
Parameters: - passw (string) – the passw which could be pin+otp
- user (User object) – The authenticating user
- options ((dict)) – dictionary of additional request parameters
Returns: returns tuple true or false for the pin match, the otpcounter (int) and the reply (dict) that will be added as additional information in the JSON response of /validate/check.
- challenge_janitor(matching_challenges, challenges)[source]¶
This is the default janitor for the challenges of a token.
The idea is to delete all challenges, which have an id lower than the matching one. Other janitors could be implemented on a token base and overwrite this behaviour.
Remarks: In later versions this will be the place to hook a dynamically loaded default token specific janitor.
Parameters: - matching_challenges (list) – the last matching challenge
- challenges (list) – all current challenges
Returns: list of all challenges, which should be deleted
- checkOtp(anOtpVal1, counter, window, options=None)[source]¶
This checks the OTP value, AFTER the upper level did the checkPIN
- return:
- counter of the matching OTP value.
- checkPin(pin, options=None)[source]¶
checkPin - test is the pin is matching
Parameters: - pin – the pin
- options – additional optional parameters, which could be token specific
Returns: boolean
- checkResponse4Challenge(user, passw, options=None, challenges=None)[source]¶
This method verifies if the given passw matches any existing challenge of the token.
It then returns the new otp_counter of the token and the list of the matching challenges.
In case of success the otp_counter needs to be > 0. The matching_challenges is passed to the method challenge_janitor() to clean up challenges.
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
- challenges (list) – A sorted list of valid challenges for this token.
Returns: tuple of (otpcounter and the list of matching challenges)
- 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.
- check_validity_period()[source]¶
This checks if the datetime.datetime.now() is within the validity period of the token.
Returns either True/False
- createChallenge(transactionid, options=None)[source]¶
This method creates a challenge, which is submitted to the user. The submitted challenge will be preserved in the challenge database.
This method is called after the method initChallenge().
Parameters: - transactionid – the id of this challenge
- options (dict) – the request context parameters / data
Returns: tuple of (bool, message, data, attributes)
The return tuple builds up like this:
bool if submit was successfull; message which is displayed in the JSON response; data is preserved in the challenge; additional attributes, which are displayed in the JSON response.
- getInfo()[source]¶
getInfo - return the status of the token rollout
Returns: return the status dict. Return type: dict
- getInitDetail(params, user=None)[source]¶
to complete the token normalisation, the response of the initialiastion should be build by the token specific method, the getInitDetails
- getOtp(curtTime='')[source]¶
The default token does not support getting the otp value will return something like:
1, pin, otpval, combined
a negative value is a failure.
- get_multi_otp(count=0, epoch_start=0, epoch_end=0, curTime=None)[source]¶
This returns a dictionary of multiple future OTP values of a token.
- parameter
- count - how many otp values should be returned epoch_start - time based tokens: start when epoch_end - time based tokens: stop when
- return
- True/False error text OTP dictionary
- incOtpCounter(counter, reset=True)[source]¶
- method
- incOtpCounter(aToken, counter)
- parameters:
- token - a token object counter - the new counter reset - optional -
- exception:
- in case of an transaction fail an exception is thrown
- side effects:
- default of reset will reset the failCounter
- initChallenge(transactionid, challenges=None, options=None)[source]¶
This method initializes the challenge.
This is a hook that is called before the method createChallenge(), which will only be called if this method returns success==true.
Thus this method can be used, to verify if there is an outstanding challenge or if a new challenge needs to be created. E.g. this hook can be used, to implement a blocking mechanism to allow the creation of a new challenge only after a certain timeout. If there is an already outstanding challenge the return value can refer to this. (s. ticket #2986)
Parameters: - transactionid (string) – the id of the new challenge
- options (dict) – the request parameters
- challenges (list) – a list of all valid challenges for this token.
Returns: tuple of ( success, transid, message, additional attributes )
The transid (the best transaction id for this request context), message, and additional attributes (dictionar) are displayed as results in the JSON response of the /validate/check request.
Only in case of success == true the next method createChallenge will be called.
- is_challenge_request(passw, user, 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.
please 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!
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
- is_challenge_response(passw, user, options=None, challenges=None)[source]¶
This method checks, if this is a request, that is the response to a previously sent 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.
Parameters: - passw (string) – password, which might be pin or pin+otp
- user (User object) – the requesting user
- options ((dict)) – dictionary of additional request parameters
- challenges – A list of challenges for this token. These challenges may be used, to identify if this request is a response for a challenge.
Returns: true or false
- is_challenge_valid(challenge=None)[source]¶
This method verifies if the given challenge is still valid.
The default implementation checks, if the challenge start is in the default validity time window.
Please note: This method does not check the response for the challenge itself. This is done by the method checkResponse4Challenge(). E.g. this very method is_challenge_valid is used by the method challenge_janitor() to clean up old challenges.
Parameters: challenge (challenge object) – The challenge to be checked Returns: true or false
- setPin(pin, param=None)[source]¶
set the PIN. The optional parameter “param” can hold the information, if the PIN is encrypted or hashed.
- setUser(user, report)[source]¶
Parameters: - user – a User() object, consisting of loginname and realm
- report – tbdf.
- set_count_auth_success_max(count)[source]¶
Sets the counter for the maximum allowed successful logins