Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions apps/provisioning_api/lib/Controller/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,9 @@ public function addUser(string $userid,
'app' => 'ocs_api',
]);
}
} else {
//Password was provided by the admin
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case 1: No password, No email = failure
Case 2: No password, Email given = username and password reset link is mailed to user
Case 3: Password given, Email given = username is mailed to user
Case 4: Password given, No email = password reset forced after login

At least that must be documented somewhere. I'm against any more magic here. I don't think the behaviour is guessable or intuitive even without this pr. We should explain what Nextcloud is actually are going to do and/or give the admin a change to pick the action.

@jancborchardt

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also Password given, No email is what I usually do for developing 🤣 Need to test something with a different user. Create user with password and no email, Login => Forced password reset 😠

I know that's unusual but this PR is a behavioural change. I'm sure there is someone out there happy with the current approach. People will complain about this change if there is no way to turn it off.

For example: A self-service for account creation. People are able to create a user account for Nextcloud with a internal tool. Password is only visible to user. With this change they have to reset their password again for a account just created seconds ago.

$this->editUser($userid, 'initial', 'true');
}

return new DataResponse(['id' => $userid]);
Expand Down Expand Up @@ -520,6 +523,7 @@ public function editUser(string $userId, string $key, string $value): DataRespon
$permittedFields[] = AccountManager::PROPERTY_WEBSITE;
$permittedFields[] = AccountManager::PROPERTY_TWITTER;
$permittedFields[] = 'quota';
$permittedFields[] = 'initial';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you find something more specific? Perhaps forcePasswordReset? initial is very generic.

} else {
// No rights
throw new OCSException('', \OCP\API::RESPOND_UNAUTHORISED);
Expand Down Expand Up @@ -594,6 +598,9 @@ public function editUser(string $userId, string $key, string $value): DataRespon
$this->accountManager->updateUser($targetUser, $userAccount);
}
break;
case 'initial':
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create a constant like AccountManager::PROPERTY_INITIAL

$this->config->setUserValue($targetUser->getUID(), 'core', 'initial', $value);
break;
default:
throw new OCSException('', 103);
}
Expand Down
7 changes: 7 additions & 0 deletions core/Controller/LoginController.php
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,13 @@ public function tryLogin(string $user,
$result->getErrorMessage()
);
}

if($this->config->getUserValue($user, 'core', 'initial') === 'true') {
$token = $this->config->getUserKeys($user, 'login_token')[0];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. The right way to do this:

Take the password reset token logic from NewUserMailHelper. Perhaps we need to find a better way for this. A generatePasswordResetToken method. If the user login and initial is set generate a password reset token and forward the user.

@rullzer @ChristophWurst

$token = str_replace('/', 'A', $token);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this about making the value a get parameter? If so please use urlencode.

return new RedirectResponse(
$this->urlGenerator->linkToRouteAbsolute('core.lost.resetform', ['userId' => $user, 'token' => $token]));
}

if ($result->getRedirectUrl() !== null) {
return new RedirectResponse($result->getRedirectUrl());
Expand Down
10 changes: 10 additions & 0 deletions core/Controller/LostController.php
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,15 @@ protected function checkPasswordResetToken($token, $userId) {
throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
}

if($this->config->getUserValue($userId, 'core', 'initial') === 'true')

$token = $this->config->getUserKeys($userId, 'login_token')[0];
$token = str_replace('/', 'A', $token);

if($token === $token) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😕

return true;
}
Comment on lines +202 to +209
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That change makes it possible to overtake any account if you know the userId and the user has not changed the password yet.


$encryptedToken = $this->config->getUserValue($userId, 'core', 'lostpassword', null);
if ($encryptedToken === null) {
throw new \Exception($this->l10n->t('Couldn\'t reset password because the token is invalid'));
Expand Down Expand Up @@ -317,6 +326,7 @@ public function setPassword($token, $userId, $password, $proceed) {
$this->twoFactorManager->clearTwoFactorPending($userId);

$this->config->deleteUserValue($userId, 'core', 'lostpassword');
$this->config->deleteUserValue($userId, 'core', 'initial');
@\OC::$server->getUserSession()->unsetMagicInCookie();
} catch (HintException $e){
return $this->error($e->getHint());
Expand Down