[Bug]: macOS/iOS/iPadOS cannot sync calendar/contacts when >1 users with e-mail address defined
Nobody has claimed this yet.
- Dominant language
- PHP
- Stars
- 36.9k
- Forks
- 5.2k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 713
Description
⚠️ This issue respects the following points: ⚠️
- This is a bug, not a question or a configuration/webserver/proxy issue.
- This issue is not already reported on Github OR Nextcloud Community Forum (I've searched it).
- Nextcloud Server is up to date. See Maintenance and Release Schedule for supported versions.
- I agree to follow Nextcloud's Code of Conduct.
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
- Fresh install of Nexctloud, with calendar and contacts apps installed and enabled
- Create a second user.
- Configure e-mail address for both users.
- 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
401response to include theWWW-Authenticateheader.
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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