nextcloud / nextcloud/server

[Bug]: macOS/iOS/iPadOS cannot sync calendar/contacts when >1 users with e-mail address defined

Open
#53,057 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

0. Needs triage 31-feedback bug feature: authentication feature: dav hotspot: account name handling
Dominant language
PHP
Stars
36.9k
Forks
5.2k
Avg merge
2d 3h
Merged PRs (30d)
713

Description

⚠️ This issue respects the following points: ⚠️
Bug description

With more than 1 user defined in Nextcloud, and more than 1 user has an e-mail address configured, macOS/iOS/iPadOS cannot sync calendar/contacts. An exception OCA\DAV\Connector\Sabre\Exception\PasswordLoginForbidden is thrown:

$ curl --include https://<hostname>/remote.php/dav/
HTTP/1.1 401 Unauthorized
Server: nginx
Date: Thu, 22 May 2025 19:06:49 GMT
Content-Type: application/xml; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: oc_sessionPassphrase=RXDztJLyoDRp923hwng4vvxCkh2fGnMpjbs830%2BfyPrQ9JvdSmfFnGSzqlovM6Lj1TPeDal3XzLEa5HFjBVQRaTEU9z2Jbdtl4kcNue431bFIqQ9NCHa3d4P1YD9aaz%2F; path=/; secure; HttpOnly; SameSite=Lax
Set-Cookie: __Host-nc_sameSiteCookielax=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax
Set-Cookie: __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=strict
Set-Cookie: ocm5z7doren9=e07eec820efc58873de063d5b5825ac5; path=/; secure; HttpOnly; SameSite=Lax
Content-Security-Policy: default-src 'none';
Referrer-Policy: no-referrer
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: none
X-Robots-Tag: noindex, nofollow
X-XSS-Protection: 1; mode=block

<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:o="http://owncloud.org/ns">
  <s:exception>OCA\DAV\Connector\Sabre\Exception\PasswordLoginForbidden</s:exception>
  <s:message/>
  <o:hint xmlns:o="o:">password login forbidden</o:hint>
</d:error>

My guess is that macOS/iOS/iPadOS is not trying authentication because the first request does not result in a response that has the WWW-Authenticate header.

If I remove e-mail addresses for all users (or all except for one), the request includes that header:

$ curl --include https://<hostname>/remote.php/dav/
HTTP/1.1 401 Unauthorized
Server: nginx
Date: Thu, 22 May 2025 19:07:56 GMT
Content-Type: application/xml; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: oc_sessionPassphrase=LJbJKSoSJrD7Dw6Wu%2BCulITnImV3yFYmJWs%2FGWjjJNE4vC4SbRu4sPNFZTbLvVlKL7zBsfUIegw72EuZvBP%2Fr%2FgvJG19mTw4imbWCigg8UJlSkbw6gAMzWFUqMDAPHdQ; path=/; secure; HttpOnly; SameSite=Lax
Set-Cookie: __Host-nc_sameSiteCookielax=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax
Set-Cookie: __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=strict
Content-Security-Policy: default-src 'none';
Set-Cookie: ocm5z7doren9=02559bd0641a022ab43a77b3ea13f750; path=/; secure; HttpOnly; SameSite=Lax
WWW-Authenticate: Basic realm="Nextcloud", charset="UTF-8"
Referrer-Policy: no-referrer
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: none
X-Robots-Tag: noindex, nofollow
X-XSS-Protection: 1; mode=block

<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
  <s:exception>Sabre\DAV\Exception\NotAuthenticated</s:exception>
  <s:message>No public access to this resource., AppAPIAuth has not passed, Username or password was incorrect, No 'Authorization: Bearer' header found. Either the client didn't send one, or the server is mis-configured, Username or password was incorrect</s:message>
</d:error>

Some further debugging lead me to the discovery that isTwoFactorEnforced("") in lib/private/User/Session.php always returns true in the above situation, due to $this->manager->getByEmail($username) with an emty $username returning the full list of users instead of, what I would expect, none.

My workaround for now is:

--- lib/private/Config/UserConfig.php.orig	2025-05-22 21:05:32.699409552 +0200
+++ lib/private/Config/UserConfig.php	2025-05-22 21:21:45.985359597 +0200
@@ -477,7 +477,7 @@
 		$qb->andWhere($qb->expr()->eq('configkey', $qb->createNamedParameter($key)));
 
 		$configValueColumn = ($this->connection->getDatabaseProvider() === IDBConnection::PLATFORM_ORACLE) ? $qb->expr()->castColumn('configvalue', IQueryBuilder::PARAM_STR) : 'configvalue';
-		if ($this->isUpgradedTo31()) {
+		if (false && $this->isUpgradedTo31()) {
 			// search within 'indexed' OR 'configvalue' only if 'flags' is set as not indexed
 			// TODO: when implementing config lexicon remove the searches on 'configvalue' if value is set as indexed
 			if (is_array($value)) {

I have not yet seen any negative side-effects from this.

Steps to reproduce
  1. Fresh install of Nexctloud, with calendar and contacts apps installed and enabled
  2. Create a second user.
  3. Configure e-mail address for both users.
  4. Try to configure caldav or carddav on macOS/iOS/iPadOS.

I have tested this with a clean install using sqlite as well as mysql.

Expected behavior
  • macOS/iOS/iPadOS to keep on syncing caldav/carddav without authentication errors.
  • macOS/iOS/iPadOS to be able to configure a new caldav/carddav configuration.
  • getByEmail("") to return no users instead of all.
  • a 401 response to include the WWW-Authenticate header.
Nextcloud Server version

31

Operating system

Debian/Ubuntu

PHP engine version

PHP 8.2

Web server

Nginx

Database engine version

MariaDB

Is this bug present after an update or on a fresh install?

Fresh Nextcloud Server install

Are you using the Nextcloud Server Encryption module?

Encryption is Disabled

What user-backends are you using?
  • Default user-backend (database)
  • LDAP/ Active Directory
  • SSO - SAML
  • Other
Configuration report
{
    "system": {
        "instanceid": "***REMOVED SENSITIVE VALUE***",
        "passwordsalt": "***REMOVED SENSITIVE VALUE***",
        "secret": "***REMOVED SENSITIVE VALUE***",
        "trusted_domains": [
            "ncsqlite.opzes.nl"
        ],
        "datadirectory": "***REMOVED SENSITIVE VALUE***",
        "dbtype": "sqlite3",
        "version": "31.0.5.1",
        "overwrite.cli.url": "https:\/\/<hostname>",
        "installed": true
    }
}
List of activated Apps
Enabled:
  - activity: 4.0.0
  - app_api: 5.0.2
  - bruteforcesettings: 4.0.0
  - calendar: 5.2.4
  - circles: 31.0.0
  - cloud_federation_api: 1.14.0
  - comments: 1.21.0
  - contacts: 7.1.1
  - contactsinteraction: 1.12.0
  - dashboard: 7.11.0
  - dav: 1.33.0
  - federatedfilesharing: 1.21.0
  - federation: 1.21.0
  - files: 2.3.1
  - files_downloadlimit: 4.0.0
  - files_pdfviewer: 4.0.0
  - files_reminders: 1.4.0
  - files_sharing: 1.23.1
  - files_trashbin: 1.21.0
  - files_versions: 1.24.0
  - firstrunwizard: 4.0.0
  - logreader: 4.0.0
  - lookup_server_connector: 1.19.0
  - nextcloud_announcements: 3.0.0
  - notifications: 4.0.0
  - oauth2: 1.19.1
  - password_policy: 3.0.0
  - photos: 4.0.0-dev.1
  - privacy: 3.0.0
  - profile: 1.0.0
  - provisioning_api: 1.21.0
  - recommendations: 4.0.0
  - related_resources: 2.0.0
  - serverinfo: 3.0.0
  - settings: 1.14.0
  - sharebymail: 1.21.0
  - support: 3.0.0
  - survey_client: 3.0.0
  - systemtags: 1.21.1
  - text: 5.0.0
  - theming: 2.6.1
  - twofactor_backupcodes: 1.20.0
  - updatenotification: 1.21.0
  - user_status: 1.11.0
  - viewer: 4.0.0
  - weather_status: 1.11.0
  - webhook_listeners: 1.2.0
  - workflowengine: 2.13.0
Disabled:
  - admin_audit: 1.21.0
  - encryption: 2.19.0
  - files_external: 1.23.0
  - suspicious_login: 9.0.1
  - twofactor_nextcloud_notification: 5.0.0
  - twofactor_totp: 13.0.0-dev.0
  - user_ldap: 1.22.0
Nextcloud Signing status
No errors have been found.
Nextcloud Logs

When configuring a new client, no log line is written to data/nextcloud.log. When an existing client configuration tries to re-authenticate after a second user has an e-mail address configured, a line like this is added:

{"reqId":"t5UoU4ZTbgdf2dHbpIgO","level":2,"time":"2025-05-22T19:33:28+00:00","remoteAddr":"<redacted>","user":"--","app":"core","method":"PROPFIND","url":"/remote.php/dav/addressbooks/users/admin/z-app-generated--contactsinteraction--recent/","message":"Login failed: '' (Remote IP: '<redacted>')","userAgent":"iOS/18.5 (22F76) dataaccessd/1.0","version":"31.0.5.1","data":{"app":"core"}}
Nginx logs

This is when configuring a new client on iPhone:

<redacted> - - [22/May/2025:21:35:17 +0200] "PROPFIND /.well-known/caldav HTTP/1.1" 301 162 "-" "iOS/18.5 (22F76) accountsd/1.0"
<redacted> - - [22/May/2025:21:35:30 +0200] "PROPFIND /remote.php/dav/ HTTP/1.1" 401 311 "-" "iOS/18.5 (22F76) accountsd/1.0"
<redacted> - - [22/May/2025:21:35:30 +0200] "PROPFIND / HTTP/1.1" 405 150 "-" "iOS/18.5 (22F76) accountsd/1.0"
<redacted> - - [22/May/2025:21:35:30 +0200] "PROPFIND /principals/ HTTP/1.1" 405 5 "-" "iOS/18.5 (22F76) accountsd/1.0"
<redacted> - - [22/May/2025:21:35:31 +0200] "PROPFIND /calendar/dav/admin/user/ HTTP/1.1" 405 5 "-" "iOS/18.5 (22F76) accountsd/1.0"
Additional info

No response

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 in lib/private/User/Session.php by tracing isTwoFactorEnforced("") and the manager->getByEmail($username) call. Review the related lookup behavior in lib/private/Config/UserConfig.php, reproduce the DAV request with multiple users having email addresses, and verify that getByEmail("") finds no users and the 401 response includes WWW-Authenticate.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, macos, mariadb, nginx, php
Domain
api, authentication, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.