/token/init returns "Cannot pass user_object as well as user, resolver, realm in policy"

Hi,

I have setup PrivacyIdea 3.3 and SimpleSAMLphp, and the privacyidea authproc filters for SSP.

When the SSP module makes a POST to /token/init to register a token for a user, PrivacyIdea responds with “Cannot pass user_object as well as user, resolver, realm in policy”

The SSP module is POSTing

'user' => 'steve.cirrus.stratus_gmail.com@monitor-invite-mfa',
'genkey' => 1,
'type' => 'totp',
'description' => 'Enrolled with simpleSAMLphp'

PrivacyIdea logs:

[2020-06-15 14:31:35,823][35][139747332105984][WARNING][privacyidea.lib.policy:672] Cannot pass user_object as well as user, resolver, realm in policy (None, 'admin', 'enrollTOTP'). <steve.cirrus.stratus_gmail.com.monitor-invite-mfa-sql-resolver@monitor-invite-mfa> - steve.cirrus.stratus_gmail.com@monitor-invite-mfa@None in resolver monitor-invite-mfa-sql-resolver
[2020-06-15 14:31:35,823][35][139747332105984][WARNING][privacyidea.lib.policy:673] Possible programming error:   File "/opt/privacyidea/lib/python3.6/site-packages/flask/app.py", line 2463, in __call__
     return self.wsgi_app(environ, start_response)
   File "/opt/privacyidea/lib/python3.6/site-packages/flask/app.py", line 2446, in wsgi_app
     response = self.full_dispatch_request()
   File "/opt/privacyidea/lib/python3.6/site-packages/flask/app.py", line 1949, in full_dispatch_request
     rv = self.dispatch_request()
   File "/opt/privacyidea/lib/python3.6/site-packages/flask/app.py", line 1935, in dispatch_request
     return self.view_functions[rule.endpoint](**req.view_args)
   File "/opt/privacyidea/lib/python3.6/site-packages/privacyidea/api/lib/prepolicy.py", line 151, in policy_wrapper
     return wrapped_function(*args, **kwds)
   File "/opt/privacyidea/lib/python3.6/site-packages/privacyidea/api/lib/prepolicy.py", line 151, in policy_wrapper
     return wrapped_function(*args, **kwds)
   File "/opt/privacyidea/lib/python3.6/site-packages/privacyidea/api/lib/prepolicy.py", line 150, in policy_wrapper
     action=self.action)
   File "/opt/privacyidea/lib/python3.6/site-packages/privacyidea/api/lib/prepolicy.py", line 1056, in check_token_init
     user_object=request.User).allowed()
   File "/opt/privacyidea/lib/python3.6/site-packages/privacyidea/lib/policy.py", line 2327, in allowed
     policies_defined = self.any(write_to_audit_log=write_to_audit_log)
   File "/opt/privacyidea/lib/python3.6/site-packages/privacyidea/lib/policy.py", line 2287, in any
     return bool(self.policies(write_to_audit_log=write_to_audit_log))
   File "/opt/privacyidea/lib/python3.6/site-packages/privacyidea/lib/policy.py", line 2279, in policies
     **self._match_kwargs)
   File "/opt/privacyidea/lib/python3.6/site-packages/privacyidea/lib/log.py", line 194, in log_wrapper
     f_result = func(*args, **kwds)
   File "/opt/privacyidea/lib/python3.6/site-packages/privacyidea/lib/policy.py", line 668, in match_policies
     tb_str = ''.join(traceback.format_stack())
 
 [2020-06-15 14:31:35,824][35][139747332105984][DEBUG][privacyidea.lib.auditmodules.base:186] Entering log with arguments (<privacyidea.lib.auditmodules.sqlaudit.Audit object at 0x7f195cf566d8>, {'info': "ERR905: Cannot pass user_object as well as user, resolver, realm in policy (None, 'admin', 'enrollTOTP')"}) and keywords {}

(there are also a lot of earlier logs lines prior to the error).

I don’t have many policies (increased timeouts for logins, removed welcome message).
I’ve tried creating policies to address the above issue to no avail.

The privacyidea logs do say “Possible programming error”.

How do I diagnose this further?

Thanks.

Hello Patrick,

welcome to the privacyidea community.

the first line is the interesting part:

The following user_object is passed:

  • usernname: steve.cirrus.stratus_gmail.com
  • resolver: monitor-invite-mfa-sql-resolver
  • realm: monitor-invite-mfa

But the following paramters are given:

  • username: steve.cirrus.stratus_gmail.com@monitor-invite-mfa
  • resolver: monitor-invite-mfa-sql-resolver
  • realm: None

So it might be that you have a mixup in your splitAtSign-Setting, the loginnames and the default realm? No default realm?

So you need to take a look at the name of the user and what actually the realm is.

By the way: I personally never liked the feature to enroll tokens during login a lot :wink:

By the way: You should upgrade to privacyIDEA 3.3.3. This cal also help with this error.

Thanks for the pointers Cornelius.

I was able to track the issue down further, and perhaps there is a mismatch between my (or the SSP module’s) expectations and that of the policy code.

The SSP module’s enrollToken method only sends the user (name), not the realm

$params = array(
        "user" => $state["Attributes"][$this->serverconfig['uidKey']][0],
        "genkey" => 1,
        "type" => $this->serverconfig['tokenType'],
        "description" => "Enrolled with simpleSAMLphp",
    );

We therefor set it up to send login@realm (in my case I’m sending steve.cirrus.stratus_gmail.com@monitor-invite-mfa).

PrivacyIdea receives the API call, and before_after.py calls get_user_from_param. This has logic about splitting on @ and works as we expect.
I see it working in the logs:

[2020-06-16 15:19:16,472][35][139747340498688][DEBUG][privacyidea.lib.user:198] Exiting split_user with result (‘steve.cirrus.stratus_gmail.com’, ‘monitor-invite-mfa’
)
[2020-06-16 15:19:16,475][35][139747340498688][INFO][privacyidea.lib.user:233] user ‘steve.cirrus.stratus_gmail.com’ found in resolver ‘monitor-invite-mfa-sql-resolve
r’
[2020-06-16 15:19:16,477][35][139747340498688][DEBUG][privacyidea.lib.user:198] Exiting get_user_from_param with result <steve.cirrus.stratus_gmail.com.monitor-invite
-mfa-sql-resolver@monitor-invite-mfa>

The code path continues, and a bunch of data (including some of the original request parameters) is passed into the policy match_policies method.
This first check that the user param I sent in the request matches the login in the user object. Of course this does not match since the user param I sent was login@realm and the one in the user object has been split.

Right now my “fix” is to patch the SSP module to send the user and realm separately (so I pre-split things in the php code.)

So is the expectation that /token/init should work if the user is submitted as login@realm? Or should it always be used with login and realm sent separately?

thanks for any tips.

  • Patrick

I would “expect” it, to work this way. But all other scritps or modules and the UI itself does it with a dedicated realm. We also do not have unit test for this API call, so we probably have not been aware of, that it might be used that way.

But I can confirm, that it indeed breaks, if you pass the realm with the @sign within the username. However, we need to check if it is supposed to work this way (I am not sure if my expectations are right), since the @sign-spliting very originally was introduced for user authentication via /validate/check and /auth.

So to be clean, I recommend to go with your fix using a dedicated realm parameter.

I face the same problem:
Users authenticate with their email-address, where the domain is exactly the realm.
Clicking “Enroll token” in the token tab top left gives this error:

ERR905: Cannot pass user_object as well as user, resolver, realm in policy (None, ‘user’, ‘enrollINDEXEDSECRET’)

but indexedsecret is NOT allowed to be enrolled! The dropdown list shows ALL tokentypes including the not activated ones.

If the user authenticates with @realm everything is working perfectly.

@Patrick_Radtke
Could you please share your fix? My php skills are not enough

Thanks
Andreas

@Andreas here is the patch. It basically just remove @realm from the username being submitted, and then submits that separately. Note that the realm is treated like a regex, which works fine for us, but if you have regex characters or a ‘/’ in your realm then you would need to escape it first with preg_quote before using it in preg_replace.

diff --git a/modules/privacyidea/lib/Auth/Process/tokenEnrollment.php b/modules/privacyidea/lib/Auth/Process/tokenEnrollment.php
index 41a8dca..336a76e 100644
--- a/modules/privacyidea/lib/Auth/Process/tokenEnrollment.php
+++ b/modules/privacyidea/lib/Auth/Process/tokenEnrollment.php
@@ -91,10 +91,11 @@ class sspmod_privacyidea_Auth_Process_tokenEnrollment extends SimpleSAML_Auth_Pr
 	public function enrollToken (&$state) {
 		$params        = array(
-			"user" => $state["Attributes"][$this->serverconfig['uidKey']][0],
+			"user" => preg_replace('/@' . $this->serverconfig['realm']. '$/', '', $state["Attributes"][$this->serverconfig['uidKey']][0]),
 			"genkey" => 1,
 			"type" => $this->serverconfig['tokenType'],
 			"description" => "Enrolled with simpleSAMLphp",
+                  "realm" =>  $this->serverconfig['realm'],
 		);
 		$headers = array(
 			"authorization: " . $this->auth_token,
@@ -126,4 +127,4 @@ class sspmod_privacyidea_Auth_Process_tokenEnrollment extends SimpleSAML_Auth_Pr
 			return true;
 		}
 	}
-}
\ No newline at end of file
+}

Hi @Patrick_Radtke @AAuer
It could be that you are experiencing a side effect.

Please check your privacyIDEA installation:

  1. Do you have an LDAP resolver with more than one loginattribute configured?

  2. Is you installation using the python module ldap3==2.7? It should use version 2.6.1.

I checked my installation,

  1. yes, I have sAMAccountName, mailNickname, mail as loginattribute configured
    2: ldap3 Version is 2.6.1