Integrate Microsoft 365 users into the Nextcloud Calendar with attendee search and free/busy availability.
- Attendee Search — Search Microsoft 365 users when adding attendees to calendar events
- Free/Busy — View availability of MS365 users directly in Nextcloud Calendar
- Reply Notifications — Get notified when attendees accept, decline or tentatively accept invitations
- OAuth2 with PKCE — Secure per-user authentication with Microsoft Entra ID
- Nextcloud 28–33
- PHP 8.2+
- An App Registration in Microsoft Entra ID (Azure AD)
-
Clone or download this repository into your Nextcloud
apps/directory:cd /var/www/nextcloud/apps git clone https://github.com/sara-nl/nextcloud-microsoft-calender.git nc_ms365_calendar -
Install dependencies and build the frontend:
cd nc_ms365_calendar composer install --no-dev npm install npm run build -
Enable the app:
occ app:enable nc_ms365_calendar
- Go to Azure Portal → App registrations → New registration
- Name: e.g. "Nextcloud Calendar Integration"
- Supported account types: Single tenant (your organization)
- Redirect URI: Web →
https://your-nextcloud.com/apps/nc_ms365_calendar/oauth/callback
Add the following Delegated permissions under Microsoft Graph:
| Permission | Purpose | Admin Consent |
|---|---|---|
User.ReadBasic.All |
Search users | Required |
People.Read |
Relevant contacts | No |
Calendars.Read |
Free/busy information | No |
Calendars.Read.Shared |
Shared calendar free/busy | No |
offline_access |
Refresh tokens | No |
Click Grant admin consent after adding permissions.
- Go to Certificates & secrets → New client secret
- Copy the secret value (it's only shown once)
You'll need:
- Tenant ID — found on the Overview page of your App Registration
- Client ID (Application ID) — found on the Overview page
- Client Secret — from step 3
Go to Administration settings → Microsoft 365 Calendar Integration and enter:
- Tenant ID
- Client ID
- Client Secret
- Cache TTL — How long search results are cached (default: 300s)
- Reply Notifications — Send notifications when attendees respond to invitations (toggle on/off)
Each user connects their own Microsoft 365 account:
- Go to Personal settings → Microsoft 365 Calendar
- Click Connect to Microsoft 365
- Sign in with your Microsoft account and grant permissions
When a user searches for attendees in the Calendar app, the app queries the Microsoft Graph API using multiple strategies:
- People API — Finds frequently contacted people
- Users API — Searches by display name and email
- Results are merged, deduplicated, and cached (5-minute TTL)
The app registers a Sabre DAV plugin that intercepts CalDAV free/busy requests:
- Identifies external attendees (not in Nextcloud)
- Queries Microsoft Graph
/me/calendar/getSchedule - Merges MS365 availability with Nextcloud's response
- Works transparently with any CalDAV client (Apple Calendar, Thunderbird, etc.)
Status mapping:
| MS365 Status | CalDAV Status |
|---|---|
busy |
BUSY |
tentative |
BUSY-TENTATIVE |
oof (Out of Office) |
BUSY-UNAVAILABLE |
workingElsewhere |
BUSY-TENTATIVE |
When enabled in admin settings, the app monitors calendar event updates for PARTSTAT changes (accept/decline/tentative) and sends Nextcloud notifications to the event organizer.
# Install dependencies
composer install
npm install
# Build frontend
npm run build
# Watch mode
npm run dev
# Run tests
./vendor/bin/phpunitAGPL-3.0-or-later