Skip to content

feat(provisioning): Master password support#9008

Merged
ChristophWurst merged 1 commit intomainfrom
feat/master-password
Nov 9, 2023
Merged

feat(provisioning): Master password support#9008
ChristophWurst merged 1 commit intomainfrom
feat/master-password

Conversation

@ChristophWurst
Copy link
Copy Markdown
Member

@ChristophWurst ChristophWurst commented Oct 27, 2023

Amended and squashed version of #8917.

How to test

  1. Build feat: Allow a static password for auth ChristophWurst/docker-imap-devel#13
  2. Set up provisioning for the static password from the config file

How to test – Alternative

  1. Set up provisioning with your testing account's email address and the "static" IMAP password 😉
  2. Verify the account works

@ChristophWurst

This comment was marked as outdated.

Comment thread lib/Db/Provisioning.php Outdated
Comment thread src/components/settings/ProvisioningSettings.vue Outdated
@mickenordin
Copy link
Copy Markdown
Contributor

Will this be merged in time for 3.5.0? I saw that you guys were tagging beta releases?

@ChristophWurst
Copy link
Copy Markdown
Member Author

Yes, no rush. 3.5 will only be branched off in a week. This PR should make it.

@ChristophWurst ChristophWurst marked this pull request as ready for review November 7, 2023 10:15
@ChristophWurst
Copy link
Copy Markdown
Member Author

@mickenordin may I ask you to also give the latest state a final test? 🙏

@mickenordin
Copy link
Copy Markdown
Contributor

@mickenordin may I ask you to also give the latest state a final test? 🙏

Definetly! Will get right on it!

@mickenordin
Copy link
Copy Markdown
Contributor

mickenordin commented Nov 7, 2023

Unfortunately this does no longer work for me. The app now fails to detect that the user should see the mail box, and instead claims that it is disabled due to being a SSO account.

The actual code works though it seems. If I set the master password and give a local user the same email it works, but not for a user signed in with single signon.

I am pretty sure that this used to work, so I am not sure what happened here. How can it have stopped detecting that the user account should be able to see the mail box?

What I did to set this up by the way was this:

git clone https://github.com/nextcloud/mail 
cd mail
git checkout v3.5.0-beta1
wget https://patch-diff.githubusercontent.com/raw/nextcloud/mail/pull/9008.diff
patch -p1 < 9008.diff
git add .
git commit -m "Master password patch"
make build-js-production
make appstore

@ChristophWurst
Copy link
Copy Markdown
Member Author

I'm also unable to test the changes at the moment

@mickenordin
Copy link
Copy Markdown
Contributor

mickenordin commented Nov 8, 2023

@ChristophWurst I see what is missing now, it is the check in

src/components/Navigation.vue in https://github.com/nextcloud/mail/pull/8917/files#diff-578fcad0646f9b6ab3e4f8bbe2f8f946e54d39670c0da653db620aaead7d9663

And the corresponding getter in store

@mickenordin
Copy link
Copy Markdown
Contributor

mickenordin commented Nov 8, 2023 via email

@mickenordin
Copy link
Copy Markdown
Contributor

mickenordin commented Nov 8, 2023

The patch above fixes the issue and here it is as an attachement as well.
8917.diff.txt

@ChristophWurst
Copy link
Copy Markdown
Member Author

The feature works again 🚀

Copy link
Copy Markdown
Member Author

@ChristophWurst ChristophWurst left a comment

Choose a reason for hiding this comment

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

👍 on @mickenordin's changes :)

Thanks a lot

SSO users do not have a password set, and the auto provisioning of mail
does not work for SSO user. It is also inconvenient to synchronize the
password database between Nextcloud and the mail server used.

So to allow SSO user to use the mail app we can instead configure a
shared password for all users, this will work well with for example
Dovecot that has a concept of a "master password"[0] that can be used to
authenticate users. To use this feature we must convince the mail app
that the user has a password available, which we can set with occ like
so:
```
  ./occ config:app:set mail master_password --value 'very-secret-master-password'
```
We can then configure dovecot to allow this password from the Nextcloud
server, in this example 89.46.21.198:
```
passdb {
  args = password=very-secret-master-password allow_nets=89.46.21.198/32
  driver = static
}
```
If we configure postfix to use SASL auth against dovecot, we can then
both send and recieve mail from Nextcloud mail app, for SSO users.

0. https://doc.dovecot.org/configuration_manual/authentication/master_users/

Co-Authored-By: Christoph Wurst <[email protected]>
Signed-off-by: Micke Nordin <[email protected]>
Signed-off-by: Christoph Wurst <[email protected]>
Comment thread lib/Db/Provisioning.php
* @method bool|null getMasterPasswordEnabled()
* @method void setMasterPasswordEnabled(bool $masterPasswordEnabled)
* @method string|null getMasterPassword()
* @method void setMasterPassword(string $masterPassword)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
* @method void setMasterPassword(string $masterPassword)
* @method void setMasterPassword(?string $masterPassword)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To unset the master password?

Comment thread lib/Db/Provisioning.php
* @method bool|null getMasterPasswordEnabled()
* @method void setMasterPasswordEnabled(bool $masterPasswordEnabled)
* @method string|null getMasterPassword()
* @method void setMasterPassword(string $masterPassword)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

To unset the master password?

$masterPasswordEnabled = $provisioning->getMasterPasswordEnabled();
if ($masterPasswordEnabled && $masterPassword !== null) {
$password = $masterPassword;
$this->logger->debug('Password set to master password for ' . $user->getUID());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

early return here? Having both a master pw and a regular pw is unneccessary, right?

@ChristophWurst ChristophWurst merged commit 76c2dad into main Nov 9, 2023
@ChristophWurst ChristophWurst deleted the feat/master-password branch November 9, 2023 15:49
@sevmonster
Copy link
Copy Markdown

sevmonster commented Dec 8, 2023

This PR doesn't work if the user never had a password to begin with. This is the case in my environment as none of my users were created with a password, they were all created via user_saml.

public function beforeController($controller, $methodName) {
$user = $this->userSession->getUser();
if ($user === null) {
// Nothing to update
return;
}
$configs = $this->provisioningManager->getConfigs();
if ($configs === []) {
return;
}
try {
$this->provisioningManager->provisionSingleUser($configs, $user);
$password = $this->credentialStore->getLoginCredentials()->getPassword();
// FIXME: Need to check for an empty string here too?
// The password is empty (and not null) when using WebAuthn passwordless login.
// Maybe research other providers as well.
// Ref \OCA\Mail\Controller\PageController::index()
// -> inital state for password-is-unavailable
if ($password === null) {
// Nothing to update, might be passwordless signin
$this->logger->debug('No password set for ' . $user->getUID());
return;
}
$this->provisioningManager->updatePassword(
$user,
$password,
$configs
);

I am not sure why the password logic is split between two places like this when it seems the only place updatePassword is used is in the tests. Could all of this logic be moved into the updatePassword function for simplicity and also to help fix this regression? I am not a NC dev so I don't know if this split is a requirement for some reason.

I have monkeypatched this in my environment by always calling updatePassword with the empty string as a password, which is then set overriden in the function by the master password, since none of my provisionable users have a password set anyway.

@mickenordin
Copy link
Copy Markdown
Contributor

My users also don't have a password set and were created by the global site selector. This is what this PR aims to fix by allowing the administrator to set a master password. Can you explain a bit more clearly what is not working, and what the regression is?

@ChristophWurst
Copy link
Copy Markdown
Member Author

Please put this into a new ticket.

@sevmonster
Copy link
Copy Markdown

sevmonster commented Dec 15, 2023

My users also don't have a password set and were created by the global site selector.

Your users probably have something set as their password in the database; they would not be able to use provisioned accounts at all if they didn't. Users without any password set (be it in use or if they signed in via SSO) will have an exception thrown, and updatePassword() is never called. I could reproduce this with all of my users, whom have blank passwords in the database. Please check your actual database for values in the password row.

Can you explain a bit more clearly what is not working, and what the regression is?

@mickenordin @ChristophWurst #9175

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants