Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
quenenni opened this issue Oct 27, 2021 · 11 comments
Assignees
Labels
Milestone

Comments

@quenenni
Copy link

quenenni commented Oct 27, 2021

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.

  • I was able to have the carddav plugin working in RC 1.5.0 (with an app password in NC).
    I works very well, but as soon as I disconnect and reconnect, it doesn't work anymore.

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

  • I also tried to configure a "Preset Addressbook" with bearer authentication, but without success.
    Here is my config:
$prefs['Personnal'] = [
    // required attributes
    'name'         =>  'Personnal',
    'url'          =>  'https://cloud.mydomaincloud.name/remote.php/dav/addressbooks/users/%l/contacts/',

    // required attributes unless passwordless authentication is used (Kerberos)
    'username'     =>  '',
    'password'     =>  '%b',

    // optional attributes
    'active'       =>  true,
    'readonly'     =>  false,
    'refresh_time' => '00:10:00',

    // attributes that are fixed (i.e., not editable by the user) and auto-updated for this preset
    'fixed'        =>  [],

    // always require these attributes, even for addressbook view
    'require_always' => ['email'],

    // hide this preset from CardDAV preferences section so users can't even see it
    'hide' => false,
];

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

Thanks,
Kenny

logs_with_app_passwd.tar.gz
logs_with_bearer_auth.tar.gz

@quenenni
Copy link
Author

I found this post from last november (#319 (comment))

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
Copy link
Author

quenenni commented Oct 27, 2021

I followed more the post I referenced and read the PR to add webdav access to OIDC token (pulsejet/nextcloud-oidc-login#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
Copy link
Owner

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
Copy link
Owner

Concerning bearer authentication:

  • the nextcloud-oidc-login app is the only app I am aware of that supports bearer authentication at the DAV backend of nextcloud, so yes, you would have to switch to that app and use OIDC instead of SAML
  • the initial pull request is already merged and part of the latest release of that app, but it has a few constraints:
    • the access token needs to be a JWT (this is what the open pull request attempts to address)
    • the access token issued to the roundcube client needs to contain the nextcloud client ID in the audience aud claim

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
Copy link
Author

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
Copy link
Author

quenenni commented Oct 28, 2021

$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
Copy link
Author

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 mstilkerich self-assigned this Oct 28, 2021
@mstilkerich
Copy link
Owner

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
Copy link
Owner

mstilkerich commented Oct 28, 2021

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.

@mstilkerich mstilkerich added this to the 4.2.2 milestone Oct 28, 2021
@quenenni
Copy link
Author

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
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants