Source code for privacyidea.lib.tokens.registrationtoken

# -*- coding: utf-8 -*-
#  privacyIDEA
#  Aug 12, 2014 Cornelius Kölbel
#  License:  AGPLv3
#  contact:
#  2015-01-29 Adapt during migration to flask
#             Cornelius Kölbel <>
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
# License as published by the Free Software Foundation; either
# version 3 of the License, or any later version.
# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# You should have received a copy of the GNU Affero General Public
# License along with this program.  If not, see <>.
This file contains the definition of the RegisterToken class.

The code is tested in

import logging

from privacyidea.lib.utils import to_unicode
from privacyidea.lib.tokens.passwordtoken import PasswordTokenClass
from privacyidea.lib.log import log_with
from privacyidea.lib.decorators import check_token_locked
from privacyidea.lib import _
from privacyidea.lib.policy import SCOPE, ACTION, GROUP
from privacyidea.api.lib.prepolicy import _generate_pin_from_policy


optional = True
required = False

log = logging.getLogger(__name__)

[docs]class RegistrationTokenClass(PasswordTokenClass): """ Token to implement a registration code. It can be used to create a registration code or a "TAN" which can be used once by a user to authenticate somewhere. After this registration code is used, the token is automatically deleted. The idea is to provide a workflow, where the user can get a registration code by e.g. postal mail and then use this code as the initial first factor to authenticate to the UI to enroll real tokens. A registration code can be created by an administrative task with the token/init api like this: **Example Authentication Request**: .. sourcecode:: http POST /token/init HTTP/1.1 Host: Accept: application/json type=registration user=cornelius realm=realm1 **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "detail": { "registrationcode": "12345808124095097608" }, "id": 1, "jsonrpc": "2.0", "result": { "status": true, "value": true }, "version": "privacyIDEA unknown" } """ def __init__(self, aToken): PasswordTokenClass.__init__(self, aToken) self.hKeyRequired = False self.set_type(u"registration") self.otp_len = DEFAULT_LENGTH self.otp_contents = DEFAULT_CONTENTS
[docs] @staticmethod def get_class_type(): return "registration"
[docs] @staticmethod def get_class_prefix(): return "REG"
[docs] @staticmethod @log_with(log) def get_class_info(key=None, ret='all'): """ returns a subtree of the token definition :param key: subsection identifier :type key: string :param ret: default return value, if nothing is found :type ret: user defined :return: subsection if key exists or user defined :rtype: dict or scalar """ res = {'type': 'registration', 'title': 'Registration Code Token', 'description': _('Registration: A token that creates a ' 'registration code that ' 'can be used as a second factor once.'), 'init': {}, 'config': {}, 'user': [], # This tokentype is enrollable in the UI for... 'ui_enroll': ["admin"], 'policy': { SCOPE.ENROLL: { ACTION.MAXTOKENUSER: { 'type': 'int', 'desc': _("The user may only have this maximum number of registration tokens assigned."), 'group': GROUP.TOKEN }, ACTION.MAXACTIVETOKENUSER: { 'type': 'int', 'desc': _( "The user may only have this maximum number of active registration tokens assigned."), 'group': GROUP.TOKEN } } }, } if key: ret = res.get(key) else: if ret == 'all': ret = res return ret
[docs] def update(self, param): """ This method is called during the initialization process. :param param: parameters from the token init :type param: dict :return: None """ if "genkey" in param: # We do not need the genkey! We generate anyway. # Otherwise genkey and otpkey will raise an exception in # PasswordTokenClass del param["genkey"] if "registration.length" in param: size = param["registration.length"] del param["registration.length"] else: size = self.otp_len if "registration.contents" in param: contents = param["registration.contents"] del param["registration.contents"] else: contents = self.otp_contents param["otpkey"] = _generate_pin_from_policy(contents, size=int(size)) PasswordTokenClass.update(self, param)
[docs] @log_with(log, log_entry=False) @check_token_locked def post_success(self): """ Delete the registration token after successful authentication """ self.delete_token()
[docs] @log_with(log) def get_init_detail(self, params=None, user=None): """ At the end of the initialization we return the registration code. """ response_detail = PasswordTokenClass.get_init_detail(self, params, user) params = params or {} secretHOtp = self.token.get_otpkey() registrationcode = secretHOtp.getKey() response_detail["registrationcode"] = to_unicode(registrationcode) return response_detail