Repository: privacyidea/privacyidea

Issue:
User tries to assign an already assigned token
When a user tries to assign an already assigned user, the system responds back with a message like this:

    ERR1103: Token already assigned to user User(...)

This gives out unnecessarily too much information. It should just say "Token already assigned to another user"

The ``assign`` API is the same for *admin* and *user*. We could already test on the server side, if this request is done by an admin or by a user and craft the respond accordingly.

But on the library level (https://github.com/privacyidea/privacyidea/blob/master/privacyidea/lib/token.py#L1133) we currently do not have the information, if this is an admin or a user. So we would have to pass down this information from here:
https://github.com/privacyidea/privacyidea/blob/master/privacyidea/api/token.py#L425



Discussion:

Resolving patch:
diff --git a/privacyidea/api/token.py b/privacyidea/api/token.py
--- a/privacyidea/api/token.py
+++ b/privacyidea/api/token.py
@@ -422,7 +422,12 @@ def assign_api():
     serial = getParam(request.all_data, "serial", required, allow_empty=False)
     pin = getParam(request.all_data, "pin")
     encrypt_pin = getParam(request.all_data, "encryptpin")
-    res = assign_token(serial, user, pin=pin, encrypt_pin=encrypt_pin)
+    if g.logged_in_user.get("role") == "user":
+        err_message = "Token already assigned to another user."
+    else:
+        err_message = None
+    res = assign_token(serial, user, pin=pin, encrypt_pin=encrypt_pin,
+                       err_message=err_message)
     g.audit_object.log({"success": True})
     return send_result(res)
 
diff --git a/privacyidea/lib/token.py b/privacyidea/lib/token.py
--- a/privacyidea/lib/token.py
+++ b/privacyidea/lib/token.py
@@ -1102,7 +1102,7 @@ def set_defaults(serial):
 
 
 @log_with(log)
-def assign_token(serial, user, pin=None, encrypt_pin=False):
+def assign_token(serial, user, pin=None, encrypt_pin=False, err_message=None):
     """
     Assign token to a user.
     If the PIN is given, the PIN is reset.
@@ -1115,6 +1115,8 @@ def assign_token(serial, user, pin=None, encrypt_pin=False):
     :type pin: basestring
     :param encrypt_pin: Whether the PIN should be stored in an encrypted way
     :type encrypt_pin: bool
+    :param err_message: The error message, that is displayed in case the token is already assigned
+    :type err_message: basestring
 
     :return: True if the token was assigned, in case of an error an exception
     is thrown
@@ -1132,8 +1134,8 @@ def assign_token(serial, user, pin=None, encrypt_pin=False):
     old_user = tokenobject.user
     if old_user:
         log.warning("token already assigned to user: {0!r}".format(old_user))
-        raise TokenAdminError("Token already assigned to user {0!r}".format(
-                              old_user), id=1103)
+        err_message = err_message or "Token already assigned to user {0!r}".format(old_user)
+        raise TokenAdminError(err_message, id=1103)
 
     tokenobject.set_user(user)
     if pin is not None:


Test patch:
diff --git a/tests/test_api_token.py b/tests/test_api_token.py
--- a/tests/test_api_token.py
+++ b/tests/test_api_token.py
@@ -294,6 +294,33 @@ def test_04_assign_unassign_token(self):
                                            headers={'Authorization': self.at}):
             res = self.app.full_dispatch_request()
             self.assertTrue(res.status_code == 400, res)
+            result = json.loads(res.data).get("result")
+            error = result.get("error")
+            self.assertEqual(error.get("message"), "ERR1103: Token already assigned to user User(login=u'cornelius', "
+                                                   "realm=u'realm1', resolver=u'resolver1')")
+
+        # Now the user tries to assign a foreign token
+        with self.app.test_request_context('/auth',
+                                           method='POST',
+                                           data={"username":
+                                                     "selfservice@realm1",
+                                                 "password": "test"}):
+            res = self.app.full_dispatch_request()
+            self.assertTrue(res.status_code == 200, res)
+            result = json.loads(res.data).get("result")
+            self.assertTrue(result.get("status"), res.data)
+            # In self.at_user we store the user token
+            self.at_user = result.get("value").get("token")
+
+        with self.app.test_request_context('/token/assign',
+                                           method='POST',
+                                           data={"serial": "S1"},
+                                           headers={'Authorization': self.at_user}):
+            res = self.app.full_dispatch_request()
+            self.assertTrue(res.status_code == 400, res)
+            result = json.loads(res.data).get("result")
+            error = result.get("error")
+            self.assertEqual(error.get("message"), "ERR1103: Token already assigned to another user.")
 
         # Now unassign the token
         with self.app.test_request_context('/token/unassign',