def test_02_failcounter_max_totp(self):
        # Check if we can not authenticate with a token that has the maximum
        # failcounter
        user = User(login="******", realm=self.realm1)
        pin = "testTOTP"
        token = init_token({"serial": pin, "pin": pin,
                            "type": "totp", "otpkey": OTPKEY},
                           user=user)
        """
        47251644    942826
        47251645    063321
        47251646    306773
        47251647    722053
        47251648    032819
        47251649    705493
        47251650    589836
        """
        res, reply = check_user_pass(user, pin + "942826",
                                     options={"initTime": 47251644 * 30})
        self.assertTrue(res)
        # Set the failcounter to maximum failcount
        token.set_failcount(10)
        # Authentication must fail, since the failcounter is reached
        res, reply = check_user_pass(user, pin + "032819",
                                     options={"initTime": 47251648 * 30})
        self.assertFalse(res)
        self.assertEqual(reply.get("message"), "matching 1 tokens, "
                                               "Failcounter exceeded")

        remove_token(pin)
    def test_03_inc_failcounter_of_all_tokens(self):
        # If a user has more than one token and authenticates with wrong OTP
        # PIN, the failcounter on all tokens should be increased
        user = User(login="******", realm=self.realm1)
        pin1 = "pin1"
        pin2 = "pin2"
        token1 = init_token({"serial": pin1, "pin": pin1,
                             "type": "hotp", "genkey": 1}, user=user)
        token2 = init_token({"serial": pin2, "pin": pin2,
                             "type": "hotp", "genkey": 1}, user=user)

        # Authenticate with pin1 will increase first failcounter
        res, reply = check_user_pass(user, pin1 + "000000")
        self.assertEqual(res, False)
        self.assertEqual(reply.get("message"), "wrong otp value")

        self.assertEqual(token1.token.failcount, 1)
        self.assertEqual(token2.token.failcount, 0)

        # Authenticate with a wrong PIN will increase all failcounters
        res, reply = check_user_pass(user, "XXX" + "000000")
        self.assertEqual(res, False)
        self.assertEqual(reply.get("message"), "wrong otp pin")

        self.assertEqual(token1.token.failcount, 2)
        self.assertEqual(token2.token.failcount, 1)
    def test_05_autoassign_any_pin(self):
        # init a token, that does has no uwser
        self.setUp_user_realms()
        tokenobject = init_token({"serial": "UASSIGN1", "type": "hotp",
                                  "otpkey": "3132333435363738393031"
                                            "323334353637383930"},
                                 tokenrealms=[self.realm1])

        user_obj = User("autoassignuser", self.realm1)
        # unassign all tokens from the user autoassignuser
        try:
            unassign_token(None, user=user_obj)
        except Exception:
            print("no need to unassign token")

        # The request with an OTP value and a PIN of a user, who has not
        # token assigned
        builder = EnvironBuilder(method='POST',
                                 data={},
                                 headers={})
        env = builder.get_environ()
        env["REMOTE_ADDR"] = "10.0.0.1"
        g.client_ip = env["REMOTE_ADDR"]
        req = Request(env)
        req.all_data = {"user": "******", "realm": self.realm1,
                        "pass": "******"}
        # The response with a failed request
        res = {"jsonrpc": "2.0",
               "result": {"status": True,
                          "value": False},
               "version": "privacyIDEA test",
               "id": 1}
        resp = Response(json.dumps(res))

        # Set the autoassign policy
        # to "any_pin"
        set_policy(name="pol2",
                   scope=SCOPE.ENROLL,
                   action="{0!s}={1!s}".format(ACTION.AUTOASSIGN, AUTOASSIGNVALUE.NONE),
                                     client="10.0.0.0/8")
        g.policy_object = PolicyClass()

        new_response = autoassign(req, resp)
        jresult = json.loads(new_response.data)
        self.assertTrue(jresult.get("result").get("value"), jresult)
        self.assertEqual(jresult.get("detail").get("serial"), "UASSIGN1")

        # test the token with test287082 will fail
        res, dict = check_user_pass(User("autoassignuser", self.realm1),
                                    "test287082")
        self.assertFalse(res)

        # test the token with test359152 will succeed
        res, dict = check_user_pass(User("autoassignuser", self.realm1),
                                    "test359152")
        self.assertTrue(res)

        delete_policy("pol2")
    def test_36_check_user_pass(self):
        hotp_tokenobject = get_tokens(serial="hotptoken")[0]
        user = User("shadow", realm=self.realm1)
        r, reply = check_user_pass(user, "passwordasdf")
        self.assertFalse(r)
        self.assertTrue(reply.get("message") == 'The user has no tokens '
                                                'assigned', "%s" % reply)

        user = User("cornelius", realm=self.realm1)
        r, reply = check_user_pass(user, "hotppin868912")
        self.assertTrue(r)
        r, reply = check_user_pass(user, "hotppin736127")
Beispiel #5
0
    def test_36_check_user_pass(self):
        hotp_tokenobject = get_tokens(serial="hotptoken")[0]
        user = User("shadow", realm=self.realm1)
        r, reply = check_user_pass(user, "passwordasdf")
        self.assertFalse(r)
        self.assertTrue(
            reply.get("message") == 'The user has no tokens '
            'assigned', "%s" % reply)

        user = User("cornelius", realm=self.realm1)
        r, reply = check_user_pass(user, "hotppin868912")
        self.assertTrue(r)
        r, reply = check_user_pass(user, "hotppin736127")
Beispiel #6
0
    def test_01_multiple_token(self):
        set_policy("otppin",
                   scope=SCOPE.AUTH,
                   action="{0!s}=none".format(ACTION.OTPPIN))
        res, reply = check_user_pass(self.user, '')
        self.assertFalse(res)
        self.assertIn('transaction_id', reply, reply)
        tid = reply['transaction_id']
        self.assertIn('multi_challenge', reply, reply)
        self.assertEqual(len(reply['multi_challenge']), 2,
                         reply['multi_challenge'])
        self.assertIn('messages', reply, reply)
        self.assertEqual(len(reply['messages']), 2, reply['messages'])
        # check that the serials of the challenges are different
        chal1 = reply['multi_challenge'][0]
        chal2 = reply['multi_challenge'][1]
        self.assertNotEqual(chal1['serial'], chal2['serial'],
                            reply['multi_challenge'])
        self.assertEqual(chal1['transaction_id'], chal2['transaction_id'],
                         reply['multi_challenge'])
        # Now make sure that the requests contain the same challenge
        self.assertEqual(chal1['attributes']['u2fSignRequest']['challenge'],
                         chal2['attributes']['u2fSignRequest']['challenge'],
                         reply['multi_challenge'])
        # check that we have two challenges in the db with the same challenge
        chals = get_challenges(transaction_id=tid)
        self.assertEqual(len(chals), 2, chals)
        self.assertEqual(chals[0].challenge, chals[1].challenge, chals)

        delete_policy('otppin')
    def test_16_passthru_assign(self):
        user = User("cornelius", realm="r1")
        passw = "{0!s}test".format(self.valid_otp_values[1])
        options = {}
        # remove all tokens of cornelius
        remove_token(user=user)

        # create unassigned tokens in realm r1
        init_token({"type": "hotp",
                    "otpkey": "00"*20,
                    "serial": "TOKFAIL"}, tokenrealms=["r1"])
        init_token({"type": "hotp",
                    "otpkey": self.otpkey,
                    "serial": "TOKMATCH"}, tokenrealms=["r1"])

        # A user with no tokens will fail to authenticate
        self.assertEqual(get_tokens(user=user, count=True), 0)
        rv = auth_user_passthru(check_user_pass, user, passw, options)
        self.assertFalse(rv[0])
        self.assertEqual(rv[1].get("message"),
                         "The user has no tokens assigned")

        # Now add a PASSTHRU policy to a RADIUS config
        radiusmock.setdata(success=True)
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action="{0!s}=radiusconfig1".format(ACTION.PASSTHRU))
        r = add_radius("radiusconfig1", "1.2.3.4", "testing123",
                       dictionary=DICT_FILE)
        self.assertTrue(r > 0)
        set_policy(name="pol2",
                   scope=SCOPE.AUTH,
                   action="{0!s}=6:pin:1234".format(ACTION.PASSTHRU_ASSIGN))

        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        g.audit_object = FakeAudit()
        options = {"g": g}

        rv = auth_user_passthru(check_user_pass, user, passw, options=options)
        self.assertTrue(rv[0])
        self.assertTrue(u"against RADIUS server radiusconfig1 due to 'pol1'" in rv[1].get("message"))
        self.assertTrue(u"autoassigned TOKMATCH" in rv[1].get("message"))

        # Check if the token is assigned and can authenticate
        r = check_user_pass(User("cornelius", "r1"), "test{0!s}".format(self.valid_otp_values[2]))
        self.assertTrue(r[0])
        self.assertEqual(r[1].get("serial"), "TOKMATCH")

        remove_token("TOKFAIL")
        remove_token("TOKMATCH")
        delete_policy("pol1")
        delete_policy("pol2")
    def test_16_passthru_assign(self):
        user = User("cornelius", realm="r1")
        passw = "{0!s}test".format(self.valid_otp_values[1])
        options = {}
        # remove all tokens of cornelius
        remove_token(user=user)

        # create unassigned tokens in realm r1
        init_token({"type": "hotp",
                    "otpkey": "00"*20,
                    "serial": "TOKFAIL"}, tokenrealms=["r1"])
        init_token({"type": "hotp",
                    "otpkey": self.otpkey,
                    "serial": "TOKMATCH"}, tokenrealms=["r1"])

        # A user with no tokens will fail to authenticate
        self.assertEqual(get_tokens(user=user, count=True), 0)
        rv = auth_user_passthru(check_user_pass, user, passw, options)
        self.assertFalse(rv[0])
        self.assertEqual(rv[1].get("message"),
                         "The user has no tokens assigned")

        # Now add a PASSTHRU policy to a RADIUS config
        radiusmock.setdata(response=radiusmock.AccessAccept)
        set_policy(name="pol1",
                   scope=SCOPE.AUTH,
                   action="{0!s}=radiusconfig1".format(ACTION.PASSTHRU))
        r = add_radius("radiusconfig1", "1.2.3.4", "testing123",
                       dictionary=DICT_FILE)
        self.assertTrue(r > 0)
        set_policy(name="pol2",
                   scope=SCOPE.AUTH,
                   action="{0!s}=6:pin:1234".format(ACTION.PASSTHRU_ASSIGN))

        g = FakeFlaskG()
        g.policy_object = PolicyClass()
        g.audit_object = FakeAudit()
        options = {"g": g}

        rv = auth_user_passthru(check_user_pass, user, passw, options=options)
        self.assertTrue(rv[0])
        self.assertTrue(u"against RADIUS server radiusconfig1 due to 'pol1'" in rv[1].get("message"))
        self.assertTrue(u"autoassigned TOKMATCH" in rv[1].get("message"))

        # Check if the token is assigned and can authenticate
        r = check_user_pass(User("cornelius", "r1"), "test{0!s}".format(self.valid_otp_values[2]))
        self.assertTrue(r[0])
        self.assertEqual(r[1].get("serial"), "TOKMATCH")

        remove_token("TOKFAIL")
        remove_token("TOKMATCH")
        delete_policy("pol1")
        delete_policy("pol2")
 def test_47_use_yubikey_and_hotp(self):
     # fix problem https://github.com/privacyidea/privacyidea/issues/279
     user = User("cornelius", self.realm1)
     token = init_token({"type": "hotp",
                         "otpkey": self.otpkey,
                         "pin": "pin47"}, user)
     token = init_token({"type": "yubikey",
                         "otpkey": self.otpkey,
                         "pin": "pin47"}, user)
     r = check_user_pass(user, "pin47888888")
     self.assertEqual(r[0], False)
     self.assertEqual(r[1].get('message'), "wrong otp value")
Beispiel #10
0
    def test_01_failcounter_max_hotp(self):
        # Check if we can not authenticate with a token that has the maximum
        # failcounter
        user = User(login="******", realm=self.realm1)
        token = init_token(
            {
                "serial": "test47",
                "pin": "test47",
                "type": "hotp",
                "otpkey": OTPKEY
            },
            user=user)
        """                        Truncated
           Count    Hexadecimal    Decimal        HOTP
           0        4c93cf18       1284755224     755224
           1        41397eea       1094287082     287082
           2         82fef30        137359152     359152
           3        66ef7655       1726969429     969429
           4        61c5938a       1640338314     338314
           5        33c083d4        868254676     254676
           6        7256c032       1918287922     287922
           7         4e5b397         82162583     162583
           8        2823443f        673399871     399871
           9        2679dc69        645520489     520489
           10                                     403154
           11                                     481090
           12                                     868912
           13                                     736127
        """
        res, reply = check_user_pass(user, "test47287082")
        self.assertTrue(res)
        # Set the failcounter to maximum failcount
        token.set_failcount(10)
        # Authentication must fail, since the failcounter is reached
        res, reply = check_user_pass(user, "test47359152")
        self.assertFalse(res)
        self.assertEqual(reply.get("message"), "matching 1 tokens, "
                         "Failcounter exceeded")

        remove_token("test47")
Beispiel #11
0
    def test_03_inc_failcounter_of_all_tokens(self):
        # If a user has more than one token and authenticates with wrong OTP
        # PIN, the failcounter on all tokens should be increased
        user = User(login="******", realm=self.realm1)
        pin1 = "pin1"
        pin2 = "pin2"
        token1 = init_token(
            {
                "serial": pin1,
                "pin": pin1,
                "type": "hotp",
                "genkey": 1
            },
            user=user)
        token2 = init_token(
            {
                "serial": pin2,
                "pin": pin2,
                "type": "hotp",
                "genkey": 1
            },
            user=user)

        # Authenticate with pin1 will increase first failcounter
        res, reply = check_user_pass(user, pin1 + "000000")
        self.assertEqual(res, False)
        self.assertEqual(reply.get("message"), "wrong otp value")

        self.assertEqual(token1.token.failcount, 1)
        self.assertEqual(token2.token.failcount, 0)

        # Authenticate with a wrong PIN will increase all failcounters
        res, reply = check_user_pass(user, "XXX" + "000000")
        self.assertEqual(res, False)
        self.assertEqual(reply.get("message"), "wrong otp pin")

        self.assertEqual(token1.token.failcount, 2)
        self.assertEqual(token2.token.failcount, 1)
Beispiel #12
0
    def test_02_failcounter_max_totp(self):
        # Check if we can not authenticate with a token that has the maximum
        # failcounter
        user = User(login="******", realm=self.realm1)
        pin = "testTOTP"
        token = init_token(
            {
                "serial": pin,
                "pin": pin,
                "type": "totp",
                "otpkey": OTPKEY
            },
            user=user)
        """
        47251644    942826
        47251645    063321
        47251646    306773
        47251647    722053
        47251648    032819
        47251649    705493
        47251650    589836
        """
        res, reply = check_user_pass(user,
                                     pin + "942826",
                                     options={"initTime": 47251644 * 30})
        self.assertTrue(res)
        # Set the failcounter to maximum failcount
        token.set_failcount(10)
        # Authentication must fail, since the failcounter is reached
        res, reply = check_user_pass(user,
                                     pin + "032819",
                                     options={"initTime": 47251648 * 30})
        self.assertFalse(res)
        self.assertEqual(reply.get("message"), "matching 1 tokens, "
                         "Failcounter exceeded")

        remove_token(pin)
    def test_01_failcounter_max_hotp(self):
        # Check if we can not authenticate with a token that has the maximum
        # failcounter
        user = User(login="******", realm=self.realm1)
        token = init_token({"serial": "test47", "pin": "test47",
                            "type": "hotp", "otpkey": OTPKEY},
                           user=user)

        """                        Truncated
           Count    Hexadecimal    Decimal        HOTP
           0        4c93cf18       1284755224     755224
           1        41397eea       1094287082     287082
           2         82fef30        137359152     359152
           3        66ef7655       1726969429     969429
           4        61c5938a       1640338314     338314
           5        33c083d4        868254676     254676
           6        7256c032       1918287922     287922
           7         4e5b397         82162583     162583
           8        2823443f        673399871     399871
           9        2679dc69        645520489     520489
           10                                     403154
           11                                     481090
           12                                     868912
           13                                     736127
        """
        res, reply = check_user_pass(user, "test47287082")
        self.assertTrue(res)
        # Set the failcounter to maximum failcount
        token.set_failcount(10)
        # Authentication must fail, since the failcounter is reached
        res, reply = check_user_pass(user, "test47359152")
        self.assertFalse(res)
        self.assertEqual(reply.get("message"), "matching 1 tokens, "
                                               "Failcounter exceeded")

        remove_token("test47")
Beispiel #14
0
    def test_37_challenge(self):
        # We create a challenge by first sending the PIN of the HOTP token
        # then we answer the challenge by sending the OTP.

        num1 = Challenge.query.filter(Challenge.serial == "hotptoken").count()
        # The correct PIN will create a challenge
        r, reply = check_serial_pass("hotptoken", "hotppin")
        self.assertTrue(r is False, r)
        num2 = Challenge.query.filter(Challenge.serial == "hotptoken").count()
        # check that the challenge is created
        self.assertTrue(num1 + 1 == num2, (num1, num2))
        self.assertTrue(type(reply) == dict, reply)
        transaction_id = reply.get("transaction_id", "")
        self.assertTrue(len(transaction_id) > 10, reply)

        # Challenge Response, with the transaction id
        r, reply = check_serial_pass("hotptoken", "436521",
                                     {"transaction_id": transaction_id})
        self.assertTrue(r)
        self.assertTrue(
            reply.get("message") == "Found matching challenge", reply)

        # create two tokens with the same OTP Key and the same PIN, so
        # this token will create the same challenge
        # creating a challenge will not work!
        tokenobject = init_token({
            "serial": "CHALL001",
            "type": "hotp",
            "otpkey": self.otpkey
        })
        tokenobject = init_token({
            "serial": "CHALL002",
            "type": "hotp",
            "otpkey": self.otpkey
        })
        user = User("cornelius", realm=self.realm1)
        assign_token("CHALL001", user)
        assign_token("CHALL002", user)
        set_pin("CHALL001", "challpin")
        set_pin("CHALL002", "challpin")
        r, reply = check_user_pass(user, "challpin")
        self.assertFalse(r)
        self.assertTrue(
            "Multiple tokens to create a challenge found"
            in reply.get("message"), reply)
        remove_token("CHALL001")
        remove_token("CHALL002")
Beispiel #15
0
def check_webui_user(user_obj,
                     password,
                     options=None,
                     superuser_realms=None,
                     check_otp=False):
    """
    This function is used to authenticate the user at the web ui.
    It checks against the userstore or against OTP/privacyidea (check_otp).
    It returns a tuple of

    * true/false if the user authenticated successfully
    * the role of the user
    * the "detail" dictionary of the response

    :param user_obj: The user who tries to authenticate
    :type user_obj: User Object
    :param password: Password, static and or OTP
    :param options: additional options like g and clientip
    :type options: dict
    :param superuser_realms: list of realms, that contain admins
    :type superuser_realms: list
    :param check_otp: If set, the user is not authenticated against the
         userstore but against privacyidea
    :return: tuple of bool, string and dict/None
    """
    options = options or {}
    superuser_realms = superuser_realms or []
    user_auth = False
    role = ROLE.USER
    details = None

    if check_otp:
        # check if the given password matches an OTP token
        check, details = check_user_pass(user_obj, password, options=options)
        if check:
            user_auth = True
    else:
        # check the password of the user against the userstore
        if user_obj.check_password(password):
            user_auth = True

    # If the realm is in the SUPERUSER_REALM then the authorization role
    # is risen to "admin".
    if user_obj.realm in superuser_realms:
        role = ROLE.ADMIN

    return user_auth, role, details
Beispiel #16
0
def check_webui_user(user_obj,
                     password,
                     options=None,
                     superuser_realms=None,
                     check_otp=False):
    """
    This function is used to authenticate the user at the web ui.
    It checks against the userstore or against OTP/privacyidea (check_otp).
    It returns a tuple of

    * true/false if the user authenticated successfully
    * the role of the user
    * the "detail" dictionary of the response

    :param user_obj: The user who tries to authenticate
    :type user_obj: User Object
    :param password: Password, static and or OTP
    :param options: additional options like g and clientip
    :type options: dict
    :param superuser_realms: list of realms, that contain admins
    :type superuser_realms: list
    :param check_otp: If set, the user is not authenticated against the
         userstore but against privacyidea
    :return: tuple of bool, string and dict/None
    """
    options = options or {}
    superuser_realms = superuser_realms or []
    user_auth = False
    role = ROLE.USER
    details = None

    if check_otp:
        # check if the given password matches an OTP token
        check, details = check_user_pass(user_obj, password, options=options)
        if check:
            user_auth = True
    else:
        # check the password of the user against the userstore
        if user_obj.check_password(password):
            user_auth = True

    # If the realm is in the SUPERUSER_REALM then the authorization role
    # is risen to "admin".
    if user_obj.realm in superuser_realms:
        role = ROLE.ADMIN

    return user_auth, role, details
Beispiel #17
0
 def test_47_use_yubikey_and_hotp(self):
     # fix problem https://github.com/privacyidea/privacyidea/issues/279
     user = User("cornelius", self.realm1)
     token = init_token(
         {
             "type": "hotp",
             "otpkey": self.otpkey,
             "pin": "pin47"
         }, user)
     token = init_token(
         {
             "type": "yubikey",
             "otpkey": self.otpkey,
             "pin": "pin47"
         }, user)
     r = check_user_pass(user, "pin47888888")
     self.assertEqual(r[0], False)
     self.assertEqual(r[1].get('message'), "wrong otp value")
    def test_37_challenge(self):
        # We create a challenge by first sending the PIN of the HOTP token
        # then we answer the challenge by sending the OTP.

        num1 = Challenge.query.filter(Challenge.serial == "hotptoken").count()
        # The correct PIN will create a challenge
        r, reply = check_serial_pass("hotptoken", "hotppin")
        self.assertTrue(r is False, r)
        num2 = Challenge.query.filter(Challenge.serial == "hotptoken").count()
        # check that the challenge is created
        self.assertTrue(num1 + 1 == num2, (num1, num2))
        self.assertTrue(type(reply) == dict, reply)
        transaction_id = reply.get("transaction_id","")
        self.assertTrue(len(transaction_id) > 10, reply)

        # Challenge Response, with the transaction id
        r, reply = check_serial_pass("hotptoken", "436521",
                                     {"transaction_id": transaction_id})
        self.assertTrue(r)
        self.assertTrue(reply.get("message") == "Found matching challenge",
                        reply)

        # create two tokens with the same OTP Key and the same PIN, so
        # this token will create the same challenge
        # creating a challenge will not work!
        tokenobject = init_token({"serial": "CHALL001", "type": "hotp",
                                  "otpkey": self.otpkey})
        tokenobject = init_token({"serial": "CHALL002", "type": "hotp",
                                  "otpkey": self.otpkey})
        user = User("cornelius", realm=self.realm1)
        assign_token("CHALL001", user)
        assign_token("CHALL002", user)
        set_pin("CHALL001", "challpin")
        set_pin("CHALL002", "challpin")
        r, reply = check_user_pass(user, "challpin")
        self.assertFalse(r)
        self.assertTrue("Multiple tokens to create a challenge found"
                        in reply.get("message"), reply)
        remove_token("CHALL001")
        remove_token("CHALL002")
Beispiel #19
0
    def test_38_autoassign(self):
        user = User("autoassignuser", realm=self.realm1)
        tokenobject = init_token({"serial": "AUTO001", "type": "hotp",
                                  "otpkey": self.otpkey,
                                  "realm": self.realm1})

        tokenobject = init_token({"serial": "AUTO002", "type": "hotp",
                                  "otpkey": "1234",
                                  "realm": self.realm1})

        realms = get_realms_of_token("AUTO001")
        # The token is in realm1
        self.assertTrue(self.realm1 in realms, realms)
        realms = get_realms_of_token("AUTO002")
        # The token is in realm1
        self.assertTrue(self.realm1 in realms, realms)

        # Authentication by autoassign fails due to wrong password
        r, reply_dict = auto_assign_token(user, "wrong287082")
        # Nevertheless the 287082 is void, now!
        self.assertFalse(r)
        self.assertTrue("failed to authenticate against userstore"
                        in reply_dict.get("message"), reply_dict)

        # Authentication by autoassign
        r, reply_dict = auto_assign_token(user, "test399871")
        self.assertTrue(r, (r, reply_dict))
        # Token is assigned
        self.assertTrue(get_tokens(user=user, count=True) == 1, get_tokens(
            user=user))
        # Normal authentication
        r = check_user_pass(user, "test520489")
        self.assertTrue(r)

        # Now try to assign a new token to the user, which will not work,
        # as autoassignment only works for users, who have NO token.
        r, reply_dict = auto_assign_token(user, "test287082")
        # Autoassignment fails
        self.assertFalse(r)
Beispiel #20
0
def check():
    """
    check the authentication for a user or a serial number.
    Either a ``serial`` or a ``user`` is required to authenticate.
    The PIN and OTP value is sent in the parameter ``pass``.
    In case of successful authentication it returns ``result->value: true``.

    In case of a challenge response authentication a parameter ``exception=1``
    can be passed. This would result in a HTTP 500 Server Error response if
    an error occurred during sending of SMS or Email.

    In case ``/validate/radiuscheck`` is requested, the responses are
    modified as follows: A successful authentication returns an empty HTTP
    204 response. An unsuccessful authentication returns an empty HTTP
    400 response. Error responses are the same responses as for the
    ``/validate/check`` endpoint.

    :param serial: The serial number of the token, that tries to authenticate.
    :param user: The loginname/username of the user, who tries to authenticate.
    :param realm: The realm of the user, who tries to authenticate. If the
        realm is omitted, the user is looked up in the default realm.
    :param type: The tokentype of the tokens, that are taken into account during
        authentication. Requires authz policy application_tokentype.
        Is ignored when a distinct serial is given.
    :param pass: The password, that consists of the OTP PIN and the OTP value.
    :param otponly: If set to 1, only the OTP value is verified. This is used
        in the management UI. Only used with the parameter serial.
    :param transaction_id: The transaction ID for a response to a challenge
        request
    :param state: The state ID for a response to a challenge request

    :return: a json result with a boolean "result": true

    **Example Validation Request**:

        .. sourcecode:: http

           POST /validate/check HTTP/1.1
           Host: example.com
           Accept: application/json

           user=user
           realm=realm1
           pass=s3cret123456

    **Example response** for a successful authentication:

       .. sourcecode:: http

           HTTP/1.1 200 OK
           Content-Type: application/json

            {
              "detail": {
                "message": "matching 1 tokens",
                "serial": "PISP0000AB00",
                "type": "spass"
              },
              "id": 1,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": true
              },
              "version": "privacyIDEA unknown"
            }

    **Example response** for this first part of a challenge response
    authentication:

       .. sourcecode:: http

           HTTP/1.1 200 OK
           Content-Type: application/json

            {
              "detail": {
                "serial": "PIEM0000AB00",
                "type": "email",
                "transaction_id": "12345678901234567890",
                "multi_challenge: [ {"serial": "PIEM0000AB00",
                                     "transaction_id":  "12345678901234567890",
                                     "message": "Please enter otp from your
                                     email"},
                                    {"serial": "PISM12345678",
                                     "transaction_id": "12345678901234567890",
                                     "message": "Please enter otp from your
                                     SMS"}
                ]
              },
              "id": 1,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": false
              },
              "version": "privacyIDEA unknown"
            }

    In this example two challenges are triggered, one with an email and one
    with an SMS. The application and thus the user has to decide, which one
    to use. They can use either.

    .. note:: All challenge response tokens have the same transaction_id in
       this case.
    """
    user = request.User
    serial = getParam(request.all_data, "serial")
    password = getParam(request.all_data, "pass", required)
    otp_only = getParam(request.all_data, "otponly")
    token_type = getParam(request.all_data, "type")
    options = {"g": g,
               "clientip": g.client_ip}
    # Add all params to the options
    for key, value in request.all_data.items():
            if value and key not in ["g", "clientip"]:
                options[key] = value

    g.audit_object.log({"user": user.login,
                        "resolver": user.resolver,
                        "realm": user.realm})

    if serial:
        if user:
            # check if the given token belongs to the user
            if not get_tokens(user=user, serial=serial, count=True):
                raise ParameterError('Given serial does not belong to given user!')
        if not otp_only:
            result, details = check_serial_pass(serial, password, options=options)
        else:
            result, details = check_otp(serial, password)

    else:
        options["token_type"] = token_type
        result, details = check_user_pass(user, password, options=options)

    g.audit_object.log({"info": log_used_user(user, details.get("message")),
                        "success": result,
                        "serial": serial or details.get("serial"),
                        "token_type": details.get("type")})
    return send_result(result, details=details)
Beispiel #21
0
def samlcheck():
    """
    Authenticate the user and return the SAML user information.

    :param user: The loginname/username of the user, who tries to authenticate.
    :param realm: The realm of the user, who tries to authenticate. If the
        realm is omitted, the user is looked up in the default realm.
    :param pass: The password, that consists of the OTP PIN and the OTP value.

    :return: a json result with a boolean "result": true

    **Example response** for a successful authentication:

       .. sourcecode:: http

           HTTP/1.1 200 OK
           Content-Type: application/json

            {
              "detail": {
                "message": "matching 1 tokens",
                "serial": "PISP0000AB00",
                "type": "spass"
              },
              "id": 1,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": {"attributes": {
                            "username": "******",
                            "realm": "themis",
                            "mobile": null,
                            "phone": null,
                            "myOwn": "/data/file/home/koelbel",
                            "resolver": "themis",
                            "surname": "Kölbel",
                            "givenname": "Cornelius",
                            "email": null},
                          "auth": true}
              },
              "version": "privacyIDEA unknown"
            }

    The response in value->attributes can contain additional attributes
    (like "myOwn") which you can define in the LDAP resolver in the attribute
    mapping.
    """
    user = get_user_from_param(request.all_data)
    password = getParam(request.all_data, "pass", required)
    options = {"g": g, "clientip": g.client_ip}
    # Add all params to the options
    for key, value in request.all_data.items():
        if value and key not in ["g", "clientip"]:
            options[key] = value

    auth, details = check_user_pass(user, password, options=options)
    ui = user.info
    result_obj = {"auth": auth, "attributes": {}}
    if return_saml_attributes():
        # privacyIDEA's own attribute map
        result_obj["attributes"] = {
            "username": ui.get("username"),
            "realm": user.realm,
            "resolver": user.resolver,
            "email": ui.get("email"),
            "surname": ui.get("surname"),
            "givenname": ui.get("givenname"),
            "mobile": ui.get("mobile"),
            "phone": ui.get("phone")
        }
        # additional attributes
        for k, v in ui.iteritems():
            result_obj["attributes"][k] = v

    g.audit_object.log({
        "info": details.get("message"),
        "success": auth,
        "serial": details.get("serial"),
        "tokentype": details.get("type"),
        "user": user.login,
        "realm": user.realm
    })
    return send_result(result_obj, details=details)
Beispiel #22
0
def check():
    """
    check the authentication for a user or a serial number.
    Either a ``serial`` or a ``user`` is required to authenticate.
    The PIN and OTP value is sent in the parameter ``pass``.

    :param serial: The serial number of the token, that tries to authenticate.
    :param user: The loginname/username of the user, who tries to authenticate.
    :param realm: The realm of the user, who tries to authenticate. If the
        realm is omitted, the user is looked up in the default realm.
    :param pass: The password, that consists of the OTP PIN and the OTP value.
    :param transaction_id: The transaction ID for a response to a challenge
        request
    :param state: The state ID for a response to a challenge request

    :return: a json result with a boolean "result": true

    **Example response** for a successful authentication:

       .. sourcecode:: http

           HTTP/1.1 200 OK
           Content-Type: application/json

            {
              "detail": {
                "message": "matching 1 tokens",
                "serial": "PISP0000AB00",
                "type": "spass"
              },
              "id": 1,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": true
              },
              "version": "privacyIDEA unknown"
            }
    """
    user = get_user_from_param(request.all_data)
    serial = getParam(request.all_data, "serial")
    password = getParam(request.all_data, "pass", required)
    options = {"g": g, "clientip": g.client_ip}
    # Add all params to the options
    for key, value in request.all_data.items():
        if value and key not in ["g", "clientip"]:
            options[key] = value

    g.audit_object.log({"user": user.login, "realm": user.realm})

    if serial:
        result, details = check_serial_pass(serial, password, options=options)
    else:
        result, details = check_user_pass(user, password, options=options)

    g.audit_object.log({
        "info": details.get("message"),
        "success": result,
        "serial": serial or details.get("serial"),
        "tokentype": details.get("type")
    })
    return send_result(result, details=details)
Beispiel #23
0
def samlcheck():
    """
    Authenticate the user and return the SAML user information.

    :param user: The loginname/username of the user, who tries to authenticate.
    :param realm: The realm of the user, who tries to authenticate. If the
        realm is omitted, the user is looked up in the default realm.
    :param pass: The password, that consists of the OTP PIN and the OTP value.

    :return: a json result with a boolean "result": true

    **Example response** for a successful authentication:

       .. sourcecode:: http

           HTTP/1.1 200 OK
           Content-Type: application/json

            {
              "detail": {
                "message": "matching 1 tokens",
                "serial": "PISP0000AB00",
                "type": "spass"
              },
              "id": 1,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": {"auth": true,
                          "username: <loginname>,
                          "realm": ....,
                          "surname": ....,
                          "givenname": .....,
                          "mobile": ....,
                          "phone": ....,
                          "email": ....
                }
              },
              "version": "privacyIDEA unknown"
            }
    """
    user = get_user_from_param(request.all_data)
    password = getParam(request.all_data, "pass", required)
    options = {"g": g,
               "clientip": request.remote_addr}
    # Add all params to the options
    for key, value in request.all_data.items():
            if value and key not in ["g", "clientip"]:
                options[key] = value

    auth, details = check_user_pass(user, password, options=options)
    ui = user.get_user_info()
    result_obj = {"auth": auth,
                  "attributes": {"username": ui.get("username"),
                                 "realm": user.realm,
                                 "resolver": user.resolver,
                                 "email": ui.get("email"),
                                 "surname": ui.get("surname"),
                                 "givenname": ui.get("givenname"),
                                 "mobile": ui.get("mobile"),
                                 "phone": ui.get("phone")
                                 }
                  }

    g.audit_object.log({"info": details.get("message"),
                        "success": auth,
                        "serial": details.get("serial"),
                        "tokentype": details.get("type"),
                        "user": user.login,
                        "realm": user.realm})
    return send_result(result_obj, details=details)
Beispiel #24
0
def check():
    """
    check the authentication for a user or a serial number.
    Either a ``serial`` or a ``user`` is required to authenticate.
    The PIN and OTP value is sent in the parameter ``pass``.

    :param serial: The serial number of the token, that tries to authenticate.
    :param user: The loginname/username of the user, who tries to authenticate.
    :param realm: The realm of the user, who tries to authenticate. If the
        realm is omitted, the user is looked up in the default realm.
    :param pass: The password, that consists of the OTP PIN and the OTP value.
    :param transaction_id: The transaction ID for a response to a challenge
        request
    :param state: The state ID for a response to a challenge request

    :return: a json result with a boolean "result": true

    **Example response** for a successful authentication:

       .. sourcecode:: http

           HTTP/1.1 200 OK
           Content-Type: application/json

            {
              "detail": {
                "message": "matching 1 tokens",
                "serial": "PISP0000AB00",
                "type": "spass"
              },
              "id": 1,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": true
              },
              "version": "privacyIDEA unknown"
            }
    """
    user = get_user_from_param(request.all_data)
    serial = getParam(request.all_data, "serial")
    password = getParam(request.all_data, "pass", required)
    options = {"g": g,
               "clientip": request.remote_addr}
    # Add all params to the options
    for key, value in request.all_data.items():
            if value and key not in ["g", "clientip"]:
                options[key] = value

    g.audit_object.log({"user": user.login,
                        "realm": user.realm})

    if serial:
        result, details = check_serial_pass(serial, password, options=options)
    else:
        result, details = check_user_pass(user, password, options=options)

    g.audit_object.log({"info": details.get("message"),
                        "success": result,
                        "serial": serial or details.get("serial"),
                        "tokentype": details.get("type")})
    return send_result(result, details=details)
Beispiel #25
0
    def test_05_autoassign_userstore(self):
        # init a token, that does has no user
        self.setUp_user_realms()
        tokenobject = init_token(
            {
                "serial": "UASSIGN2",
                "type": "hotp",
                "otpkey": "3132333435363738393031"
                "323334353637383930"
            },
            tokenrealms=[self.realm1])
        user_obj = User("autoassignuser", self.realm1)
        # unassign all tokens from the user autoassignuser
        try:
            unassign_token(None, user=user_obj)
        except Exception:
            print("no need to unassign token")

        # The request with an OTP value and a PIN of a user, who has not
        # token assigned
        builder = EnvironBuilder(method='POST', data={}, headers={})
        env = builder.get_environ()
        env["REMOTE_ADDR"] = "10.0.0.1"
        req = Request(env)
        req.all_data = {
            "user": "******",
            "realm": self.realm1,
            "pass": "******"
        }
        # The response with a failed request
        res = {
            "jsonrpc": "2.0",
            "result": {
                "status": True,
                "value": False
            },
            "version": "privacyIDEA test",
            "id": 1
        }
        resp = Response(json.dumps(res))

        # Set the autoassign policy
        # to "userstore"
        set_policy(name="pol2",
                   scope=SCOPE.ENROLL,
                   action="%s=%s" %
                   (ACTION.AUTOASSIGN, AUTOASSIGNVALUE.USERSTORE),
                   client="10.0.0.0/8")
        g.policy_object = PolicyClass()

        new_response = autoassign(req, resp)
        jresult = json.loads(new_response.data)
        self.assertEqual(jresult.get("result").get("value"), True)
        self.assertEqual(jresult.get("detail").get("serial"), "UASSIGN2")

        # authenticate with 287082 a second time will fail
        res, dict = check_user_pass(User("autoassignuser", self.realm1),
                                    "password287082")
        self.assertFalse(res)

        # authenticate with the next OTP 359152 will succeed
        res, dict = check_user_pass(User("autoassignuser", self.realm1),
                                    "password359152")
        self.assertTrue(res)

        delete_policy("pol2")
Beispiel #26
0
def check():
    """
    check the authentication for a user or a serial number.
    Either a ``serial`` or a ``user`` is required to authenticate.
    The PIN and OTP value is sent in the parameter ``pass``.
    In case of successful authentication it returns ``result->value: true``.

    :param serial: The serial number of the token, that tries to authenticate.
    :param user: The loginname/username of the user, who tries to authenticate.
    :param realm: The realm of the user, who tries to authenticate. If the
        realm is omitted, the user is looked up in the default realm.
    :param pass: The password, that consists of the OTP PIN and the OTP value.
    :param otponly: If set to 1, only the OTP value is verified. This is used
        in the management UI. Only used with the parameter serial.
    :param transaction_id: The transaction ID for a response to a challenge
        request
    :param state: The state ID for a response to a challenge request

    :return: a json result with a boolean "result": true

    **Example Validation Request**:

        .. sourcecode:: http

           POST /validate/check HTTP/1.1
           Host: example.com
           Accept: application/json

           user=user
           realm=realm1
           pass=s3cret123456

    **Example response** for a successful authentication:

       .. sourcecode:: http

           HTTP/1.1 200 OK
           Content-Type: application/json

            {
              "detail": {
                "message": "matching 1 tokens",
                "serial": "PISP0000AB00",
                "type": "spass"
              },
              "id": 1,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": true
              },
              "version": "privacyIDEA unknown"
            }

    **Example response** for this first part of a challenge response
    authentication:

       .. sourcecode:: http

           HTTP/1.1 200 OK
           Content-Type: application/json

            {
              "detail": {
                "serial": "PIEM0000AB00",
                "type": "email",
                "transaction_id": "12345678901234567890",
                "multi_challenge: [ {"serial": "PIEM0000AB00",
                                     "transaction_id":  "12345678901234567890",
                                     "message": "Please enter otp from your
                                     email"},
                                    {"serial": "PISM12345678",
                                     "transaction_id": "12345678901234567890",
                                     "message": "Please enter otp from your
                                     SMS"}
                ]
              },
              "id": 1,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": false
              },
              "version": "privacyIDEA unknown"
            }

    In this example two challenges are triggered, one with an email and one
    with an SMS. The application and thus the user has to decide, which one
    to use. They can use either.

    .. note:: All challenge response tokens have the same transaction_id in
       this case.
    """
    #user = get_user_from_param(request.all_data)
    user = request.User
    serial = getParam(request.all_data, "serial")
    password = getParam(request.all_data, "pass", required)
    otp_only = getParam(request.all_data, "otponly")
    options = {"g": g, "clientip": g.client_ip}
    # Add all params to the options
    for key, value in request.all_data.items():
        if value and key not in ["g", "clientip"]:
            options[key] = value

    g.audit_object.log({
        "user": user.login,
        "resolver": user.resolver,
        "realm": user.realm
    })

    if serial:
        if not otp_only:
            result, details = check_serial_pass(serial,
                                                password,
                                                options=options)
        else:
            result, details = check_otp(serial, password)

    else:
        result, details = check_user_pass(user, password, options=options)

    g.audit_object.log({
        "info": details.get("message"),
        "success": result,
        "serial": serial or details.get("serial"),
        "tokentype": details.get("type")
    })
    return send_result(result, details=details)
Beispiel #27
0
def check():
    """
    check the authentication for a user or a serial number.
    Either a ``serial`` or a ``user`` is required to authenticate.
    The PIN and OTP value is sent in the parameter ``pass``.
    In case of successful authentication it returns ``result->value: true``.

    In case of a challenge response authentication a parameter ``exception=1``
    can be passed. This would result in a HTTP 500 Server Error response if
    an error occurred during sending of SMS or Email.

    In case ``/validate/radiuscheck`` is requested, the responses are
    modified as follows: A successful authentication returns an empty HTTP
    204 response. An unsuccessful authentication returns an empty HTTP
    400 response. Error responses are the same responses as for the
    ``/validate/check`` endpoint.

    :param serial: The serial number of the token, that tries to authenticate.
    :param user: The loginname/username of the user, who tries to authenticate.
    :param realm: The realm of the user, who tries to authenticate. If the
        realm is omitted, the user is looked up in the default realm.
    :param pass: The password, that consists of the OTP PIN and the OTP value.
    :param otponly: If set to 1, only the OTP value is verified. This is used
        in the management UI. Only used with the parameter serial.
    :param transaction_id: The transaction ID for a response to a challenge
        request
    :param state: The state ID for a response to a challenge request

    :return: a json result with a boolean "result": true

    **Example Validation Request**:

        .. sourcecode:: http

           POST /validate/check HTTP/1.1
           Host: example.com
           Accept: application/json

           user=user
           realm=realm1
           pass=s3cret123456

    **Example response** for a successful authentication:

       .. sourcecode:: http

           HTTP/1.1 200 OK
           Content-Type: application/json

            {
              "detail": {
                "message": "matching 1 tokens",
                "serial": "PISP0000AB00",
                "type": "spass"
              },
              "id": 1,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": true
              },
              "version": "privacyIDEA unknown"
            }

    **Example response** for this first part of a challenge response
    authentication:

       .. sourcecode:: http

           HTTP/1.1 200 OK
           Content-Type: application/json

            {
              "detail": {
                "serial": "PIEM0000AB00",
                "type": "email",
                "transaction_id": "12345678901234567890",
                "multi_challenge: [ {"serial": "PIEM0000AB00",
                                     "transaction_id":  "12345678901234567890",
                                     "message": "Please enter otp from your
                                     email"},
                                    {"serial": "PISM12345678",
                                     "transaction_id": "12345678901234567890",
                                     "message": "Please enter otp from your
                                     SMS"}
                ]
              },
              "id": 1,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": false
              },
              "version": "privacyIDEA unknown"
            }

    In this example two challenges are triggered, one with an email and one
    with an SMS. The application and thus the user has to decide, which one
    to use. They can use either.

    .. note:: All challenge response tokens have the same transaction_id in
       this case.
    """
    #user = get_user_from_param(request.all_data)
    user = request.User
    serial = getParam(request.all_data, "serial")
    password = getParam(request.all_data, "pass", required)
    otp_only = getParam(request.all_data, "otponly")
    options = {"g": g,
               "clientip": g.client_ip}
    # Add all params to the options
    for key, value in request.all_data.items():
            if value and key not in ["g", "clientip"]:
                options[key] = value

    g.audit_object.log({"user": user.login,
                        "resolver": user.resolver,
                        "realm": user.realm})

    if serial:
        if not otp_only:
            result, details = check_serial_pass(serial, password, options=options)
        else:
            result, details = check_otp(serial, password)

    else:
        result, details = check_user_pass(user, password, options=options)

    g.audit_object.log({"info": details.get("message"),
                        "success": result,
                        "serial": serial or details.get("serial"),
                        "tokentype": details.get("type")})
    return send_result(result, details=details)
Beispiel #28
0
def samlcheck():
    """
    Authenticate the user and return the SAML user information.

    :param user: The loginname/username of the user, who tries to authenticate.
    :param realm: The realm of the user, who tries to authenticate. If the
        realm is omitted, the user is looked up in the default realm.
    :param pass: The password, that consists of the OTP PIN and the OTP value.

    :return: a json result with a boolean "result": true

    **Example response** for a successful authentication:

       .. sourcecode:: http

           HTTP/1.1 200 OK
           Content-Type: application/json

            {
              "detail": {
                "message": "matching 1 tokens",
                "serial": "PISP0000AB00",
                "type": "spass"
              },
              "id": 1,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": {"attributes": {
                            "username": "******",
                            "realm": "themis",
                            "mobile": null,
                            "phone": null,
                            "myOwn": "/data/file/home/koelbel",
                            "resolver": "themis",
                            "surname": "Kölbel",
                            "givenname": "Cornelius",
                            "email": null},
                          "auth": true}
              },
              "version": "privacyIDEA unknown"
            }

    The response in value->attributes can contain additional attributes
    (like "myOwn") which you can define in the LDAP resolver in the attribute
    mapping.
    """
    user = get_user_from_param(request.all_data)
    password = getParam(request.all_data, "pass", required)
    options = {"g": g,
               "clientip": g.client_ip}
    # Add all params to the options
    for key, value in request.all_data.items():
            if value and key not in ["g", "clientip"]:
                options[key] = value

    auth, details = check_user_pass(user, password, options=options)
    ui = user.info
    result_obj = {"auth": auth,
                  "attributes": {}}
    if return_saml_attributes():
        if auth or return_saml_attributes_on_fail():
            # privacyIDEA's own attribute map
            result_obj["attributes"] = {"username": ui.get("username"),
                                        "realm": user.realm,
                                        "resolver": user.resolver,
                                        "email": ui.get("email"),
                                        "surname": ui.get("surname"),
                                        "givenname": ui.get("givenname"),
                                        "mobile": ui.get("mobile"),
                                        "phone": ui.get("phone")
                                        }
            # additional attributes
            for k, v in ui.items():
                result_obj["attributes"][k] = v

    g.audit_object.log({"info": details.get("message"),
                        "success": auth,
                        "serial": details.get("serial"),
                        "tokentype": details.get("type"),
                        "user": user.login,
                        "resolver": user.resolver,
                        "realm": user.realm})
    return send_result(result_obj, details=details)
Beispiel #29
0
def check():
    """
    check the authentication for a user or a serial number.
    Either a ``serial`` or a ``user`` is required to authenticate.
    The PIN and OTP value is sent in the parameter ``pass``.
    In case of successful authentication it returns ``result->value: true``.

    In case of a challenge response authentication a parameter ``exception=1``
    can be passed. This would result in a HTTP 500 Server Error response if
    an error occurred during sending of SMS or Email.

    In case ``/validate/radiuscheck`` is requested, the responses are
    modified as follows: A successful authentication returns an empty ``HTTP
    204`` response. An unsuccessful authentication returns an empty ``HTTP
    400`` response. Error responses are the same responses as for the
    ``/validate/check`` endpoint.

    :param serial: The serial number of the token, that tries to authenticate.
    :param user: The loginname/username of the user, who tries to authenticate.
    :param realm: The realm of the user, who tries to authenticate. If the
        realm is omitted, the user is looked up in the default realm.
    :param type: The tokentype of the tokens, that are taken into account during
        authentication. Requires the *authz* policy :ref:`application_tokentype_policy`.
        It is ignored when a distinct serial is given.
    :param pass: The password, that consists of the OTP PIN and the OTP value.
    :param otponly: If set to 1, only the OTP value is verified. This is used
        in the management UI. Only used with the parameter serial.
    :param transaction_id: The transaction ID for a response to a challenge
        request
    :param state: The state ID for a response to a challenge request

    :return: a json result with a boolean "result": true

    **Example Validation Request**:

        .. sourcecode:: http

            POST /validate/check HTTP/1.1
            Host: example.com
            Accept: application/json

            user=user
            realm=realm1
            pass=s3cret123456

    **Example response** for a successful authentication:

        .. sourcecode:: http

            HTTP/1.1 200 OK
            Content-Type: application/json

            {
              "detail": {
                "message": "matching 1 tokens",
                "serial": "PISP0000AB00",
                "type": "spass"
              },
              "id": 1,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": true
              },
              "version": "privacyIDEA unknown"
            }

    **Example response** for this first part of a challenge response authentication:

        .. sourcecode:: http

            HTTP/1.1 200 OK
            Content-Type: application/json

            {
              "detail": {
                "serial": "PIEM0000AB00",
                "type": "email",
                "transaction_id": "12345678901234567890",
                "multi_challenge: [ {"serial": "PIEM0000AB00",
                                     "transaction_id":  "12345678901234567890",
                                     "message": "Please enter otp from your
                                     email",
                                     "client_mode": "interactive"},
                                    {"serial": "PISM12345678",
                                     "transaction_id": "12345678901234567890",
                                     "message": "Please enter otp from your
                                     SMS",
                                     "client_mode": "interactive"}
                ]
              },
              "id": 2,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": false
              },
              "version": "privacyIDEA unknown"
            }

    In this example two challenges are triggered, one with an email and one
    with an SMS. The application and thus the user has to decide, which one
    to use. They can use either.

    The challenges also contain the information of the "client_mode". This
    tells the plugin, whether it should display an input field to ask for the
    OTP value or e.g. to poll for an answered authentication.
    Read more at :ref:`client_modes`.

    .. note:: All challenge response tokens have the same ``transaction_id`` in
       this case.


    **Example response** for a successful authentication with ``/samlcheck``:

       .. sourcecode:: http

           HTTP/1.1 200 OK
           Content-Type: application/json

            {
              "detail": {
                "message": "matching 1 tokens",
                "serial": "PISP0000AB00",
                "type": "spass"
              },
              "id": 1,
              "jsonrpc": "2.0",
              "result": {
                "status": true,
                "value": {"attributes": {
                            "username": "******",
                            "realm": "themis",
                            "mobile": null,
                            "phone": null,
                            "myOwn": "/data/file/home/koelbel",
                            "resolver": "themis",
                            "surname": "Kölbel",
                            "givenname": "Cornelius",
                            "email": null},
                          "auth": true}
              },
              "version": "privacyIDEA unknown"
            }

    The response in ``value->attributes`` can contain additional attributes
    (like "myOwn") which you can define in the LDAP resolver in the attribute
    mapping.
    """
    user = request.User
    serial = getParam(request.all_data, "serial")
    password = getParam(request.all_data, "pass", required)
    otp_only = getParam(request.all_data, "otponly")
    token_type = getParam(request.all_data, "type")
    options = {"g": g, "clientip": g.client_ip, "user": user}
    # Add all params to the options
    for key, value in request.all_data.items():
        if value and key not in ["g", "clientip", "user"]:
            options[key] = value

    g.audit_object.log({
        "user": user.login,
        "resolver": user.resolver,
        "realm": user.realm
    })

    if serial:
        if user:
            # check if the given token belongs to the user
            if not get_tokens(user=user, serial=serial, count=True):
                raise ParameterError(
                    'Given serial does not belong to given user!')
        if not otp_only:
            success, details = check_serial_pass(serial,
                                                 password,
                                                 options=options)
        else:
            success, details = check_otp(serial, password)
        result = success

    else:
        options["token_type"] = token_type
        success, details = check_user_pass(user, password, options=options)
        result = success
        if request.path.endswith("samlcheck"):
            ui = user.info
            result = {"auth": success, "attributes": {}}
            if return_saml_attributes():
                if success or return_saml_attributes_on_fail():
                    # privacyIDEA's own attribute map
                    result["attributes"] = {
                        "username": ui.get("username"),
                        "realm": user.realm,
                        "resolver": user.resolver,
                        "email": ui.get("email"),
                        "surname": ui.get("surname"),
                        "givenname": ui.get("givenname"),
                        "mobile": ui.get("mobile"),
                        "phone": ui.get("phone")
                    }
                    # additional attributes
                    for k, v in ui.items():
                        result["attributes"][k] = v

    g.audit_object.log({
        "info": log_used_user(user, details.get("message")),
        "success": success,
        "serial": serial or details.get("serial"),
        "token_type": details.get("type")
    })
    return send_result(result, rid=2, details=details)