Two connectors, both
type: oauth_pkce, share this page: Microsoft Personal
(microsoft) and Microsoft Work or School (microsoft_work). Catalog entry:
src/gaia/connectors/catalog/microsoft.py
The authority each connector signs in against is spec data, not an
environment variable — every connect, refresh, and daemon restart resolves it
the same way, regardless of what environment the process happens to be
running in.
There are two ways to sign in to either connector:
- Browser (PKCE) — the default. Needs an Azure App registration you create once (below). Best when you control your own app registration.
- Device code —
gaia connectors connect <id> --device. You enter a short code at a Microsoft URL; no loopback redirect. This is the zero-setup path when a pre-registered public client ID is supplied via env var. See Device-code sign-in below.
What you’ll need (browser flow)
Microsoft requires every app — including GAIA running locally — to identify itself with an App registration that you create once in the Azure portal, per connector (personal and work/school each need their own client credentials; do not reuse one registration’s client ID for both). For a single-developer machine each registration takes a few minutes and is free. You will register an app and paste a single value into the GAIA Agent UI: an Application (client) ID. Unlike Google, the standard desktop flow needs no client secret — Microsoft forbids secrets for public (desktop) clients. GAIA stores the Client ID encrypted in your OS keyring, per connector.Step 1 — Register an app in Azure
- Go to the Azure portal → App registrations.
- Click New registration.
- Name:
GAIA(or whatever you like — include “Personal” or “Work” if you’re registering one for each connector). - Supported account types — pick the audience matching the connector you’re
registering for:
- Microsoft Personal (
microsoft): choose Personal Microsoft accounts only (or the combined “any organizational directory and personal Microsoft accounts” audience, which also authenticates fine against theconsumersauthority this connector uses). - Microsoft Work or School (
microsoft_work): choose an organizational-directory audience — Accounts in this organizational directory only for a single tenant, or Accounts in any organizational directory for multi-tenant.
- Microsoft Personal (
- Click Register. The Overview page shows the Application (client) ID — copy it for Step 3. If you registered a single-tenant work/school app, also copy the Directory (tenant) ID shown on the same page — you’ll need it in Step 3 too.
Step 2 — Add the loopback redirect URI
GAIA runs a temporary loopback web server on127.0.0.1 to receive the OAuth
callback, so it needs a localhost redirect URI of the public-client type.
- In your app, go to Authentication → Add a platform.
- Pick Mobile and desktop applications.
- Check (or add) the redirect URI
http://localhost. - Click Configure / Save.
Step 3 — Paste the Client ID into GAIA
- Launch the Agent UI:
gaia chat --ui. - Click Settings (gear) → Connections.
- Click the Microsoft Personal or Microsoft Work or School tile to expand it, matching the account type you registered in Step 1.
- Paste the Application (client) ID. Leave Client Secret blank.
On Microsoft Work or School, optionally paste the Directory (tenant)
ID into the field of the same name if you registered a single-tenant
app — this narrows sign-in to that one organization and is what lets a
background daemon (with no environment variables set) refresh correctly
without depending on the multi-tenant
organizationsdefault. - Click Save & Connect.
gaia connectors configure <id>.
GAIA will:
- Store the Client ID (and Directory tenant ID, if set) in your OS keyring (macOS Keychain on Mac, gnome-keyring/kwallet on Linux, Credential Locker on Windows).
- Open Microsoft’s consent screen in your default browser.
- Receive the callback on a temporary loopback server.
- Exchange the auth code for a refresh token (also stored in the keyring).
The refresh token is issued because GAIA requests the
offline_accessscope.
Step 4 — Per-agent grants
The connect panel shows “Grant access to these agents when you connect” — a default-on checkbox for every installed agent that declares Microsoft access. Checked agents are granted their declared Graph scopes automatically the moment the OAuth flow completes, so a fresh connect needs no follow-up command. Uncheck an agent before connecting to withhold its grant. You can adjust or revoke grants at any time from the same tile’s Per-agent grants section, or via the CLI:src/gaia/connectors/catalog/microsoft.py:
Device-code sign-in
The device-code flow skips the Azure app registration and the loopback redirect entirely — useful for headless machines, or when a public client ID is already available (e.g. an org-published GAIA app registration). In the Agent UI: with a client ID configured (env or the OAuth-client form), each Microsoft tile in Settings → Connections shows a Sign in with a code button next to Connect. Click it, then enter the displayed code at the Microsoft URL — the tile flips to Connected automatically when you finish. No browser redirect, no app registration. From the CLI:https://microsoft.com/devicelogin). Open
the URL on any device, enter the code, and approve. GAIA polls until sign-in
completes, then stores the refresh token in your OS keyring — identical to the
browser flow from that point on. Grant an agent afterward:
The client ID used for device code must be a public client with the
audience matching the connector (personal-only for
microsoft, an
organizational directory for microsoft_work) and device-code flow
allowed. GAIA does not ship a client ID — supply your own via
GAIA_MICROSOFT_CLIENT_ID / GAIA_MICROSOFT_WORK_CLIENT_ID, or use the
browser flow with your own app registration.Common issues
AADSTS50011: redirect URI mismatch
The redirect URI in your app registration doesn’t include http://localhost,
or you added it under the wrong platform. Re-check Step 2 — it must be a
Mobile and desktop applications platform redirect, not Web.
AADSTS700016 / unauthorized_client
The Client ID is wrong, or the app’s audience doesn’t match the connector you
used it with. Confirm you copied the Application (client) ID from the
Overview page and registered the audience described in Step 1 — a
personal-only app for microsoft, an organizational-directory app for
microsoft_work.
AADSTS9002346 (device code)
The app registration is personal-account-only, but you connected via
microsoft_work. Reconnect using microsoft instead — see
Device-code sign-in.
AADSTS65001 / consent required
You declined consent, or the agent is requesting a scope you didn’t approve.
Reconnect from the UI and accept the consent prompt; then grant the agent the
scope (Step 4).
Token endpoint returned no refresh_token
GAIA always requests offline_access, which is what makes Microsoft issue a
refresh token. If you see this, disconnect and reconnect from the UI to
restart the flow with the full default scope set.
Revoking access
Two places — both work, per connector:- From GAIA: Settings → Connections → the connector tile →
Disconnect. Removes that connector’s refresh token from the keyring;
the next API call for it errors with
NOT_CONNECTED. The other Microsoft connector (if connected) is unaffected. - From Microsoft: personal accounts at account.live.com/consent/Manage; work/school accounts at myapps.microsoft.com → find your app → Remove these permissions.