Skip to content

Conversation

@ChristophWurst
Copy link
Member

Env-based SAML uses the "Apache auth" mechanism to log users in. In this
code path, we first delete all existin auth tokens from the database,
before a new one is inserted. This is problematic for concurrent
requests as they might reach the same code at the same time, hence both
trying to insert a new row wit the same token (the session ID). This
also bubbles up and disables user_saml.

As the token might still be OK (both request will insert the same data),
we can actually just check if the UIDs of the conflict row is the same
as the one we want to insert right now. In that case let's just use the
existing entry and carry on.

Fixes nextcloud/user_saml#115

@rullzer
Copy link
Member

rullzer commented Nov 14, 2019

What is the code path taken here?
As in why would it happen?

@ChristophWurst
Copy link
Member Author

https://github.com/nextcloud/user_saml/blob/42d5f01b97060c8e3f8f1f04b8e3667d3da7bf5c/appinfo/app.php#L83

return self::loginWithApache($backend);

$userSession->createSessionToken($request, $uid, $uid);

@rullzer
Copy link
Member

rullzer commented Nov 14, 2019

maybe I am stupid. But I still don't get how this lead to the error...

@ChristophWurst
Copy link
Member Author

That code calls \OC\User\Session::createSessionToken. And this is the problematic section:

$this->tokenProvider->invalidateToken($sessionId);
$this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name, IToken::TEMPORARY_TOKEN, $remember);

This means. Every request tries to create its session token for the current session. The naive strategy to prevent conflicts is to first delete (invalidate) existing tokens with the same session ID:

$this->tokenProvider->invalidateToken($sessionId);
.

The problem here is that this section can reached by two independent requests of the same session at the same time. So they both clear the existing tokens. So far, so good. But then one is lucky and successfully inserts its token into the database. When the second process tries to do the same, it runs into a conflict.

Does this make sense?

@rullzer
Copy link
Member

rullzer commented Nov 18, 2019

Wouldn't just fetching the token and checking then make more sense?

@ChristophWurst
Copy link
Member Author

Wouldn't just fetching the token and checking then make more sense?

The same idea came into my mind. But it doesn't solve the problem. If you have two concurrent requests that run through the section of checking if an existing token exists at the same time, they will both get back no. Thus both will insert a row -> 💥 just like the existing code.

@rullzer
Copy link
Member

rullzer commented Nov 19, 2019

Ah mmm. Right.

But then we probably should make sure the tokens are indeed the same before returning it right? (Password, loginame etc)? Just to avoid weird bugs.

@ChristophWurst
Copy link
Member Author

But then we probably should make sure the tokens are indeed the same before returning it right? (Password, loginame etc)? Just to avoid weird bugs.

Yes, that is what I started at https://github.com/nextcloud/server/pull/17939/files#diff-b72615e7b726afb43f6043a7ec472487R82. Do we have to compare that many attributes? I think we still can rely on php not assigning the same session ID twice. Hence this should always be from the exact same session.

@rullzer
Copy link
Member

rullzer commented Nov 19, 2019

Right. if that happens we have other troubles anyways
lets do this then.

@ChristophWurst ChristophWurst added 3. to review Waiting for reviews and removed 2. developing Work in progress labels Nov 19, 2019
@ChristophWurst ChristophWurst marked this pull request as ready for review November 19, 2019 08:59
@kesselb

This comment has been minimized.

@ChristophWurst ChristophWurst force-pushed the fix/token-insert-conflict-handling branch from d0b23f3 to eec3336 Compare November 19, 2019 10:29
@ChristophWurst ChristophWurst added 4. to release Ready to be released and/or waiting for tests to finish and removed 3. to review Waiting for reviews labels Nov 20, 2019
@ChristophWurst
Copy link
Member Author

/backport to stable17

@ChristophWurst
Copy link
Member Author

/backport to stable16

@ChristophWurst
Copy link
Member Author

/backport to stable15

@rullzer rullzer force-pushed the fix/token-insert-conflict-handling branch from eec3336 to 5b43335 Compare November 25, 2019 10:36
Env-based SAML uses the "Apache auth" mechanism to log users in. In this
code path, we first delete all existin auth tokens from the database,
before a new one is inserted. This is problematic for concurrent
requests as they might reach the same code at the same time, hence both
trying to insert a new row wit the same token (the session ID). This
also bubbles up and disables user_saml.

As the token might still be OK (both request will insert the same data),
we can actually just check if the UIDs of the conflict row is the same
as the one we want to insert right now. In that case let's just use the
existing entry and carry on.

Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
@rullzer rullzer force-pushed the fix/token-insert-conflict-handling branch from 5b43335 to 0299ea0 Compare November 26, 2019 11:07
@rullzer rullzer merged commit d09f8c7 into master Nov 26, 2019
@rullzer rullzer deleted the fix/token-insert-conflict-handling branch November 26, 2019 18:48
@backportbot-nextcloud
Copy link

The backport to stable17 failed. Please do this backport manually.

@backportbot-nextcloud
Copy link

The backport to stable16 failed. Please do this backport manually.

@backportbot-nextcloud
Copy link

The backport to stable15 failed. Please do this backport manually.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4. to release Ready to be released and/or waiting for tests to finish bug feature: authentication

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Integrity constraint violation: 1062 Duplicate entry for key 'authtoken_token_index' with environment variable and mod_auth_cas

4 participants