Microsoft services — shared setup
Read this before Outlook, Microsoft Calendar, Teams, or SharePoint. One Entra app registration covers all four.
Check this first — Microsoft OAuth is off by default
Section titled “Check this first — Microsoft OAuth is off by default”source_microsoft_oauth_trigger fails unless Vorno was launched with the
MICROSOFT_OAUTH_CLIENT_ID environment variable set. The error is
“Microsoft OAuth not configured. Set MICROSOFT_OAUTH_CLIENT_ID environment variable.”
Unlike Google — where the user drops googleOAuthClientId straight into
config.json — there is no per-source config field for the Microsoft client ID.
It is read from the process environment at startup, and nothing else.
So the honest sequence is:
- Tell the user this up front, before building anything. A Microsoft source is a restart-required setup, not a click-through.
- Have them register the Entra app (below) and get the Application (client) ID.
- Have them relaunch Vorno with
MICROSOFT_OAUTH_CLIENT_ID=<client-id>in the environment. - Then create the source and authenticate.
If the user wants a Microsoft task done now and does not want to restart, use the in-app browser instead. Microsoft is the single most common case where browser-first is the right call.
Registering the Entra app
Section titled “Registering the Entra app”-
https://portal.azure.com/ → Microsoft Entra ID → App registrations → New registration.
-
Name it (e.g. “Vorno”). Choose the supported account types the user needs — single-tenant if this is one organization, or the multitenant/personal option if they use a personal Microsoft account.
-
Leave Redirect URI empty at registration. Microsoft’s own guidance is to add it afterward on the Authentication blade.
-
Manage → Authentication → Add a platform → Mobile and desktop applications. Add the redirect URI:
http://localhost/callbackThe port is deliberately omitted, and that is correct. Per RFC 8252, Entra ignores the port when matching a
localhostredirect URI —http://localhost/callbackmatcheshttp://localhost:53219/callbackand every other port. Vorno’s callback server picks an ephemeral port, so a registered URI with a fixed port would fail on most launches withAADSTS50011.Two rules that bite here:
- Do not register several localhost URIs differing only by port. Entra picks one arbitrarily and applies its platform type to all of them.
- The path is case-sensitive and is matched. It must be
/callback.
-
Manage → API permissions → Add a permission → Microsoft Graph → Delegated permissions. Add the ones the service guide names. Delegated means the app acts as the signed-in user and can reach only what that user can reach — this is what you want. Application permissions are tenant-wide and need admin consent.
-
Overview → Application (client) ID — this is the value for
MICROSOFT_OAUTH_CLIENT_ID.
No client secret is needed. A public client/native registration uses PKCE.
config.json shape
Section titled “config.json shape”{ "type": "api", "provider": "microsoft", "api": { "baseUrl": "https://graph.microsoft.com/v1.0/", "authType": "oauth", "microsoftService": "outlook", "testEndpoint": { "method": "GET", "path": "me" } }}https://graph.microsoft.com/v1.0/me is a good testEndpoint for every Microsoft
service — it is covered by User.Read, which every scope set includes.
Scopes
Section titled “Scopes”Vorno’s built-in microsoftService sets are read/write by default:
microsoftService |
Scopes |
|---|---|
outlook |
Mail.ReadWrite, Mail.Send, User.Read, offline_access |
microsoft-calendar |
Calendars.ReadWrite, User.Read, offline_access |
onedrive |
Files.ReadWrite, User.Read, offline_access |
teams |
Chat.ReadWrite, ChannelMessage.Send, User.Read, offline_access |
sharepoint |
Sites.ReadWrite.All, User.Read, offline_access |
Override with a custom scopes array when the user asked for read-only; the
service guides list the read-only equivalents. User.Read and offline_access are
force-added to any custom set, so you do not need to include them (and including
them is harmless).
Drop offline_access only if you want the connection to die when the access token
expires — it is what enables refresh.
Gotchas
Section titled “Gotchas”- Admin consent:
Sites.ReadWrite.Alland several other Graph permissions require a tenant administrator to consent. In a managed organization the user often cannot self-approve. Check before promising it will work. - The scopes are requested as full URIs (
https://graph.microsoft.com/Mail.Read), not bare names, in Vorno’s config. - Vorno authenticates against the
commontenant endpoint, which accepts both work or school accounts and personal Microsoft accounts. If the registration is single-tenant, a personal account will be rejected at sign-in. AADSTS50011always means redirect-URI mismatch. Check the path and the platform type before anything else.
Verified 2026-08-17 against Microsoft Learn’s “Redirect URI (reply URL) best practices
and limitations” (the source of the localhost port-matching rule) and Vorno’s
packages/shared/src/auth/microsoft-oauth.ts.