nextcloud / nextcloud/server

First Logins, folder generation, other user backends

Open
#21,119 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

1. to develop enhancement feature: authentication feature: filesystem feature: users and groups
Dominant language
PHP
Stars
36.9k
Forks
5.2k
Avg merge
2d 3h
Merged PRs (30d)
713

Description

How to use GitHub
  • Please use the 👍 reaction to show that you are interested into the same feature.
  • Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
  • Subscribe to receive notifications on status change and new comments.

Is your feature request related to a problem? Please describe.

User Alice logs in for the first time with user_saml. As expected their file system is prepared with the contents of the skeleton directory. What they are perhaps not aware about is, that user_saml is duplicating folder generation code, because it has to override the login mechanism.

User Bob logs in for the first time with user_ldap. Due to the password policy they have to change the initial password after first login. Having done that Bob is redirected to the files app - but is greeted with a web page of death, because the file system was not generated. Bob calls his sysadmin.

User Cecile does the same as Bob. But because their sysadmin has patched the code, Nextcloud works for them, alas the directory is not filled with the default content. Cecile cannot read the "first 7 things to do after your first login.pdf" from their organization as instructed.

Initialization of the user directory happens in \OC\User\Session::prepareUserLogin() and is called after the postLogin events are handled. user_saml is beyond that, the described user_ldap scenario forces a redirect to its password renew controller. There are other issues reported, where this issue occured even with the local backend.

User backends following the regular login chain do not know whether the user logs in for the first time or not, because the information is withhold and the new login date is already written to the database. This is also questionable, because as apps can cancel the login during postLogin event handling.

Describe the solution you'd like

  • The user folder initialization should be unbound from the login process. It shall be possible that this can happen at a later point, and/or be able to be triggered by another user backend.
  • Updating the user last login time could be a late part of the OC\Authentication\Login\Chain. It needs to be ensured that a delayed setting of this timestamp does not cause regressions.
  • The user folder initialization could be part of the OC\Authentication\Login\Chain (just before the login timestamp is set).
  • The base.php does it's own logic with handleLogin. The relevant parts might need to switch to using the OC\Authentication\Login\Chain.
  • The concrete user folder initialization method should still be part of the OC\User\Session, but become public and part of OCP\IUserSession, so it can be called out of context. Or, it shall be evaluated whether apps like user_saml should get a chance to trigger the relevant parts of the login chain handling tasks after the login was irrevocably successful.
  • a new [Login]RedirectException shall be an alternate way of cancelling the login process (currently it is LoginException) and redirect to a specified URL, instead of showing the error page. This avoids that apps have to use exit(0) to solve this case, after sending headers themselves. The LoginController ought to catch it.

Additional context

This is eventually driven by a one line patch:

diff --git a/apps/user_ldap/lib/User/User.php b/apps/user_ldap/lib/User/User.php
index 4ec7b27017..d3aa4d3695 100644
--- a/apps/user_ldap/lib/User/User.php
+++ b/apps/user_ldap/lib/User/User.php
@@ -752,6 +752,7 @@ class User {
            //handle pwdReset attribute
            if (!empty($pwdReset) && $pwdReset[0] === 'TRUE') { //user must change his password
                $this->config->setUserValue($uid, 'user_ldap', 'needsPasswordReset', 'true');
+               \OC::$server->getUserFolder($uid); // ensure user folder exists on first login
                header('Location: '.\OC::$server->getURLGenerator()->linkToRouteAbsolute(
                'user_ldap.renewPassword.showRenewPasswordForm', ['user' => $uid]));
                exit();

@rullzer @ChristophWurst this is my brain dump for today, and it well might not be the final state. I'll certainly sleep over it. Do you have thoughts about it?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading OC\User\Session::prepareUserLogin(), the OC\Authentication\Login\Chain, and the login flow in base.php and LoginController. Review apps/user_ldap/lib/User/User.php for the password-renewal redirect and compare the proposed folder initialization and LoginRedirectException paths. Done requires an agreed design covering first-login initialization, delayed login timestamps, backend-triggered flows, and redirect handling.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
authentication, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.