mstilkerich / rcmcarddav

CardDAV plugin for RoundCube Webmailer
GNU General Public License v2.0
257 stars 81 forks source link

Nextcloud addressbook sync not working after logout/re-login and also with bearer auth #361

Closed quenenni closed 2 years ago

quenenni commented 2 years ago

Hello,

I have a Roundcube / Nextcloud in SSO mode with LemonLdap as IDP, all on the same server. It's worth mentioning Roundcube and Nextcloud are not on the same domain name. Nextcloud is using SAML and Roundcube OIDC.

See attached file logs_with_app_passwd.tar.gz for the logs.

Thanks, Kenny

logs_with_app_passwd.tar.gz logs_with_bearer_auth.tar.gz

quenenni commented 2 years ago

I found this post from last november (https://github.com/mstilkerich/rcmcarddav/issues/319#issuecomment-846534208)

Is this still true, that "It appears nextcloud on the DAV API currently only accepts bearer tokens when nextcloud itself servers as the auth server, but not with a third party auth service."?

Meaning, I can't use the preset addressbook in my case.

quenenni commented 2 years ago

I followed more the post I referenced and read the PR to add webdav access to OIDC token (https://github.com/pulsejet/nextcloud-oidc-login/pull/99).

If I understood correctly, I'll have to switch from SAML to OIDC plugin in Nextcloud in order to have the preset addressbooks working with bearer authentication, correct?

And wait for the PR to be integrated in a future version of the OIDC plugin..

In the meantime, I'll try to have the carddav plugin working with an app password in Nextcloud (my first point in the original post).

Any idea why it doesn't work anymore after a disconnect / reconnect?

mstilkerich commented 2 years ago

Concerning the app passwords: I'm not aware of any such problems. In your log, I only see that the password is sent to the server but the server rejects it. The only thing I could imagine is that something goes wrong with storing the password to the DB and retrieving it later. Especially if you log into roundcube using OAuth, there will be no password to encrypt the carddav password with (if you use the default encrypted scheme).

$prefs['_GLOBAL']['pwstore_scheme'] = 'encrypted';

However, in that case it should encrypt the password with the roundcube des_key, as if you had configured

$prefs['_GLOBAL']['pwstore_scheme'] = 'des_key';

If you can access the database, you can check the password field in the carddav addressbooks table. It will contain the scheme as a prefix in braces, e.g. {ENCRYPTED}xyz. Anyway, you should not use password scheme encrypted when you log into roundcube without a password. But all this really is just a wild guess.

You can also check if the correct password is sent to the server by inspecting the Authorization header. It is redacted by default, so you would have to disable redaction. For this, edit the file src/RoundcubeLogger.php inside the carddav plugin and comment out the line

$message = $this->redactMessage($message);

like so:

// $message = $this->redactMessage($message);

Then access the addressbook again and you will get a non-redacted authorization header. If you run base64 -d on the value, it should show username:password with the proper password. If you see the correct password there, the problem is on the server side, if not, it is within rcmcarddav :-)

mstilkerich commented 2 years ago

Concerning bearer authentication:

From skimming the Lemonldap-ng docs, it should be possible to configure it work with nextcloud, but I lack experience to that end.

I tried this myself only with keycloak as the auth server and that worked fine. There is one small issue that needs to be addressed in roundcube: if you stay inside the addressbook view for a longer time and the access token expires, roundcube will not refresh the access token until you get back to the mail view. See roundcube/roundcubemail#8224

quenenni commented 2 years ago

Amazing infos you gave me here. Big thanks.

I'll need time to read / try all this. I'll come back to say how it went.

quenenni commented 2 years ago
$prefs['_GLOBAL']['pwstore_scheme'] = 'encrypted';

That's what I have. And the field password in the DB has value like this one:

{ENCRYPTED}SN160/1oOWrZ...........307dlIA+KRIA==

Then access the addressbook again and you will get a non-redacted authorization header. If you run base64 -d on the value, it should show username:password with the proper password. If you see the correct password there, the problem is on the server side, if not, it is within rcmcarddav :-)

I checked the Authorization header. What I found is username: (with no password after the ':' )

quenenni commented 2 years ago

I started again.

I tried without pwstore_scheme:

$prefs['_GLOBAL']['pwstore_scheme'] = 'plain';

It worked even after a reconnect. The Authorization header was good everytime.

I re-tried with 'encrypted'. Same problem. The Authorization header was good after I added the address book, but after a reconnect, the header only contained the username.

In both cases, the entries in the Db were correct.

I'm not a big fan having the password not encrypted in the DB. But it will do for the time being.

I'm going to test the other alternative (OIDC plugin + bearer authentication), I really would like to have that one working. I like very much the "Preset Addressbooks" config. Easy to pre-configure one for every user as opposed to the other technic.

mstilkerich commented 2 years ago

Ok, I just found that with OAuth in roundcube 1.5, roundcube sets the session password the the bearer token. That makes the check in rcmcarddav that checks if a password for encryption is available get to the conclusion there is - and it stores the carddav password in the DB, using the access token as encryption key. However, the token is short-lived - as soon as it gets replaced by a new token, rcmcarddav is not able to decrypt the password in the DB anymore.

I suggest you use des_key as the pwstore_scheme. You will still have encrypted passwords, but the session encryption key stored in the roundcube config will be used. This is a secret that the server admin has access to, not a per-user secret. It's the best that can be used if a password-less login method is used.

mstilkerich commented 2 years ago

Could you try with the latest master? It should detect OAuth login and automatically switch to des_key in the case.

A broken encrypted entry won't be fixed automatically, you will have to enter the password in the preferences again and save them to store the password with des_key scheme.

quenenni commented 2 years ago

Tested with the latest master. Indeed, it detected my var 'pwstore_scheme' was not set and it used then 'des_key' scheme. In the Db, passwords are correctly set.

And all was good after a reconnect.

Very nice. Thanks a lot.

I'm still trying the Oidc plugin. I need more time to test it in Nextcloud. I have hard time making it work with my IDP LemonLdap (but still have few ideas I need to test).

quenenni commented 2 years ago

Sorry for the delay.

I got it working with the bearer auth.

For people using LemonLdap as Idp, in " OpenID Connect Relying Parties" -> "rp-roundcube" -> Options -> Advanced -> "Additional audiences", you add the Nextcloud OIDC client ID.

If you connect to Nextcloud address books, you need the app "External user authentication" to be able to auth with bearer token via webdav.

Very very nice.