Source code for edumfa.lib.tokens.registrationtoken

# -*- coding: utf-8 -*-
#
# License:  AGPLv3
# This file is part of eduMFA. eduMFA is a fork of privacyIDEA which was forked from LinOTP.
# Copyright (c) 2024 eduMFA Project-Team
# Previous authors by privacyIDEA project:
#
# 2014 - 2015 Cornelius Kölbel <cornelius@privacyidea.org>
#
# 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
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU AFFERO GENERAL PUBLIC LICENSE for more details.
#
# You should have received a copy of the GNU Affero General Public
# License along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
"""
This file contains the definition of the RegisterToken class.

The code is tested in test_lib_tokens_registration.py.
"""

import logging

from edumfa.lib import _
from edumfa.lib.decorators import check_token_locked
from edumfa.lib.log import log_with
from edumfa.lib.policy import ACTION, GROUP, SCOPE
from edumfa.lib.tokens.passwordtoken import PasswordTokenClass
from edumfa.lib.utils import to_unicode

# We use the old default length of 24 for registration tokens
DEFAULT_LENGTH = 24
DEFAULT_CONTENTS = "cn"

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: example.com 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": "eduMFA unknown" } """ password_detail_key = "registrationcode" # nosec B105 # key name def __init__(self, aToken): PasswordTokenClass.__init__(self, aToken) self.hKeyRequired = False self.otp_len = DEFAULT_LENGTH self.otp_contents = DEFAULT_CONTENTS self.set_type("registration")
[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 neither genkey or otpkey is given we always generate the key if "genkey" not in param and "otpkey" not in param: param["genkey"] = 1 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()