Microsoft 365 Connector¶
The Microsoft 365 connector reaches an Outlook mailbox and its calendars through Microsoft Graph. One Microsoft sign-in connects two backends: Microsoft 365 Mail (m365_mail), which answers the email operations, and Microsoft 365 Calendar (m365_calendar), which answers the calendar operations. Both run through the same approval, audit, and undo path as the Google Calendar and IMAP email connectors, so their actions appear on the Audit Log page with the same undo buttons.
Work, school, and personal Microsoft accounts are supported, on macOS, Windows, Linux, and the headless server.
Signing in¶
Sign-in uses Microsoft's device code flow, which works the same on a desktop and on a server without a browser:
- Start the sign-in. Backend.AI GO asks Microsoft for a short code and shows it with the address of Microsoft's sign-in page,
https://microsoft.com/devicelogin. - Open that page in any browser, on this computer or another one, and enter the code.
- Sign in with the Microsoft account and approve the permissions listed below.
- Backend.AI GO checks with Microsoft every few seconds. Once you approve, it stores the tokens in the operating system's keychain and connects both backends.
The code expires after about 15 minutes. If it expires, or if you decline on Microsoft's page, start again.
Sign-in needs the application (client) ID of a Microsoft Entra app registration. If your organization manages one, or your build includes one, nothing is asked. Otherwise the sign-in fails with MICROSOFT_CLIENT_ID_REQUIRED until you supply one; see Registering an app.
Permissions it asks for¶
| Permission | Why |
|---|---|
openid, profile | Return an ID token whose oid and tid identify the account |
offline_access | Return a refresh token, so you are not asked to sign in every hour |
User.Read | Read the signed-in user's basic profile |
Calendars.ReadWrite | List, create, update, cancel, and respond to events |
Mail.ReadWrite | List folders and messages, save drafts, move messages to Deleted Items |
Mail.Send | Send messages and replies |
Contacts are not part of this sign-in. The contacts connector asks for Contacts.Read separately, with its own consent step.
Registering an app¶
Register your own Microsoft Entra app and supply its client ID, or use one supplied by your organization. Backend.AI GO does not ship a default client ID. To register an app:
- Open the Microsoft Entra admin center, go to App registrations, and select New registration.
- Enter a name, for example
Backend.AI GO. - Under Supported account types, choose who can sign in. Accounts in any organizational directory and personal Microsoft accounts work with the default
commontenant; a single-tenant app needs that tenant pinned (see below). - Leave Redirect URI empty. The device code flow does not use one.
- Register, then copy the Application (client) ID from the overview page.
- Open Authentication and set Allow public client flows to Yes. Backend.AI GO is a public client and keeps no client secret; without this setting Microsoft refuses the sign-in with
AADSTS7000218. - Open API permissions, choose Add a permission > Microsoft Graph > Delegated permissions, and add
offline_access,openid,profile,User.Read,Calendars.ReadWrite,Mail.ReadWrite, andMail.Send. - If your organization requires administrator consent, select Grant admin consent. Otherwise each user consents when they sign in.
Enter the client ID when the sign-in asks for it, or pass it as clientId when you start the sign-in through the API.
Supplying the client ID for an organization¶
The client ID comes from the first of these that is set:
- the organization's managed setting,
connectors.microsoft.clientId; - the client ID the user enters;
- a default compiled into the build from the
AIGO_MICROSOFT_CLIENT_IDenvironment variable.
An administrator sets the managed values through an enterprise policy, in its settings overrides:
{
"settingsOverrides": {
"connectors": {
"microsoft": {
"clientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
"tenant": "contoso.onmicrosoft.com"
}
}
}
}
connectors is a policy-only section: a user cannot change it, and a settings update that names it is refused. When clientId is set, a client ID the user enters is ignored. tenant pins the tenant: it accepts a tenant ID, a verified domain, organizations, or consumers, and a sign-in that names another tenant is refused. Without it, sign-in uses common, which accepts work, school, and personal accounts. When the tenant is pinned to a tenant ID, an account from another tenant is refused after it signs in.
If you build Backend.AI GO from source, set AIGO_MICROSOFT_CLIENT_ID in the environment of the build to give that build a default. It is read at compile time, so changing it later has no effect on a build that already exists:
Network and national clouds¶
Sign-in goes to the microsoftLogin service endpoint (https://login.microsoftonline.com/) and every mail and calendar call to the microsoftGraph endpoint (https://graph.microsoft.com/). Both appear under managed service endpoints, so an organization can point them at a national cloud, add them to an egress allowlist, or switch them off. When either is switched off, or the install runs in air-gapped mode, sign-in and every Microsoft call are refused before any connection opens.
What each operation does¶
Mail and calendar requests are the email and calendar operations with provider: "microsoft". Mail requests name messages by messageId and search with a plain-text query; the IMAP fields uid, criteria, and originalUid are refused for a Microsoft account, and the Microsoft fields are refused for an IMAP account. Message and event ids are Microsoft's immutable ids, which stay the same when a message moves between folders.
| Operation | Approval | Undo |
|---|---|---|
| List calendars, list events, get an event | none | nothing to undo |
| Create an event | none | Cancels the event; with attendees, Microsoft sends them a cancellation |
| Update an event | asked | Restores the fields it had before, best effort |
| Cancel an event | asked | Creates the event again; a meeting comes back marked [Cancelled in error] and attendees get a new invitation |
| Respond to an invitation | none | Sends your earlier response again |
| List folders, list or fetch or search messages | none | nothing to undo |
| Send, reply | asked for a first-time recipient | Moves your sent copy to Deleted Items within the account's window; the recipient keeps the message |
| Save a draft | none | Deletes the draft |
| Delete a message | asked | Moves it back to the folder it was in |
Events listed with both a start and an end use the calendar view, so a recurring meeting shows each occurrence. Times are returned in UTC. Two things Microsoft does not allow are refused rather than ignored: setting a response back to "not responded", and cancelling a meeting you organize without telling the attendees (Microsoft always tells them).
An event that you were invited to can be removed from your calendar, but undoing that cannot bring the invitation back; ask the organizer to send it again.
Messages to other people wait first¶
Sending, replying, and calendar changes that notify attendees (an invitation, an update or a cancellation of a meeting you organize) wait out the account's window before they run once the outbox is available, so an undo inside the window means nothing was sent. The mail window is unsendWindowSecs and the calendar window is cancelUnsendWindowSecs; both default to 30 seconds and can be set up to 300 when you sign in or connect. The mail window also bounds how long undo is offered after a message has gone out.
Accounts and tokens¶
Tokens live in the operating system's keychain under connector:microsoft:<account id>, and no response from Backend.AI GO ever contains one. The two backends of an account share one session, so a token refresh made for mail also serves the calendar. Microsoft replaces the refresh token each time it is used, and the new one is stored before anything else uses the session.
Each audit entry records the account that made it, identified by a hash of the account's Microsoft tenant and object ids. If a different Microsoft account later signs in under the same account id, undo of the earlier entries is refused instead of acting on the new account's mailbox or calendar.
Disconnecting an account removes both backends and deletes its tokens from the keychain. Microsoft has no way for a public client to revoke its own refresh token, so the deleted token expires on Microsoft's side. To remove the app's access immediately, remove it from your account's apps at myapps.microsoft.com.
After the app restarts, a signed-in account connects again with the activate call below, without a new sign-in.
If the keychain cannot save a refreshed sign-in, calls fail until it is unlocked and the save succeeds. A saved sign-in without its verified account identity requires signing in again.
REST API¶
The headless server exposes the same functions. Each route requires the agent_write scope, except the status route, which requires agent_read.
| Route | What it does |
|---|---|
POST /api/v1/connectors/microsoft/sign-in | Start a sign-in. Body: accountId, and optionally clientId, tenant, unsendWindowSecs, cancelUnsendWindowSecs |
POST /api/v1/connectors/microsoft/sign-in/poll | Poll once with loginSessionId. status is pending, approved, expired, cancelled, or error |
POST /api/v1/connectors/microsoft/sign-in/cancel | Cancel a sign-in |
GET /api/v1/connectors/microsoft/accounts/{accountId} | Whether the account is signed in and connected, and where a new sign-in's client ID comes from |
POST /api/v1/connectors/microsoft/activate | Connect an account that is already signed in |
DELETE /api/v1/connectors/microsoft/accounts/{accountId} | Disconnect the account and delete its tokens |
Mail and calendar calls use the email and calendar routes, for example POST /api/v1/connectors/email/send with "provider": "microsoft".
Troubleshooting¶
| Message | What to do |
|---|---|
MICROSOFT_CLIENT_ID_REQUIRED | Enter the client ID of your app registration, or ask your administrator to manage one |
MICROSOFT_PUBLIC_CLIENT_REQUIRED (AADSTS7000218) | Turn on Allow public client flows in the app registration |
MICROSOFT_APPLICATION_NOT_FOUND (AADSTS700016) | Check the application client ID and the tenant where it was registered |
MICROSOFT_CONSENT_REQUIRED (AADSTS65001, AADSTS90094) | Grant the delegated permissions, with administrator consent when required |
MICROSOFT_TENANT_MISMATCH | Use an account and app registration in the configured tenant |
the sign-in ... expired or was revoked | Sign in again; the refresh token is no longer valid |
permission denied | The sign-in is missing a permission. Add it to the app registration and sign in again |
operation 'connector' is disabled in air-gapped mode | The install is air-gapped; Microsoft 365 is unavailable |