Microsoft Teams — platform admin setup
This page is for the platform administrator running a FastLinkIt instance — the person operating flnk.it or a self-hosted equivalent. End users who just want to use Teams meetings should read Microsoft Teams integration instead.
Before users can connect their Microsoft accounts to your FastLinkIt instance, you must register a multi-tenant application in Microsoft Entra ID (the new name for Azure Active Directory). This is a one-time setup per FastLinkIt deployment.
The end-user OAuth flow uses your app registration as the trust anchor — each user grants delegated permissions to your app, and your app calls Microsoft Graph on their behalf using their per-user tokens.
Step 1 — Register the app in Entra ID
- Sign in to the Microsoft Entra admin center with an admin account.
- Go to Identity → Applications → App registrations.
- Click + New registration.
- Fill in:
- Name:
FastLinkIt(or whatever you want — users will see this on the consent screen). - Supported account types: choose Accounts in any organizational directory (Any Azure AD directory — Multitenant) and personal Microsoft accounts. Multitenant lets users from any organisation connect with their own work/school account. Personal accounts can sign in to OAuth but cannot use the meeting-creation API — the user-facing Integrations UI surfaces a warning when that happens.
- Redirect URI: select Web, enter
https://your-domain.example/api/teams/callback. For the production flnk.it instance this ishttps://flnk.it/api/teams/callback. The path is fixed by theTeamsConnectEndpoints.csroute.
- Name:
- Click Register.
Step 2 — Note the Client ID
On the app's Overview page, copy the Application (client) ID. You'll paste it into FastLinkIt config in step 5.
Step 3 — Generate a client secret
- Left sidebar → Certificates & secrets.
- Tab Client secrets → + New client secret.
- Description:
FastLinkIt production(or similar). - Expiry: 24 months (or the longest your security policy allows). You'll need to rotate before this expires.
- Click Add.
- Copy the secret VALUE immediately. Entra ID hides it after you leave this page. The
Secret IDis not what you need — copy the Value column.
Step 4 — Add API permissions
- Left sidebar → API permissions.
- Click + Add a permission → Microsoft Graph → Delegated permissions.
- Search and tick all four:
| Permission | What it does |
|---|---|
OnlineMeetings.ReadWrite |
Create and read Teams meeting objects |
Calendars.ReadWrite |
Create the calendar event with the meeting attached. Required since v2 of the integration moved from /me/onlineMeetings to /me/events |
User.Read |
Sign in and read profile (used to display the connected account email in the Integrations UI) |
offline_access |
Receive a refresh token so the integration keeps working after the access token expires (1 hour) |
- Click Add permissions.
All four are user-consentable, so each end user grants them at OAuth time without needing admin approval. However, if a user's tenant has Users can consent to apps disabled, the user will see a Need admin approval page. The user can either:
- Send the consent URL to their tenant admin.
- Their tenant admin grants tenant-wide consent on their copy of the app. Multitenant apps appear in each consenting tenant's Entra ID portal under Enterprise applications the first time anyone from that tenant signs in.
You as the FastLinkIt platform admin do not need to do anything per-tenant. Each external tenant manages its own consent for your app.
Step 5 — Wire the credentials into FastLinkIt config
Open appsettings.json, appsettings.Production.json, or set environment variables — same key path:
"MicrosoftTeams": {
"ClientId": "<paste the Application (client) ID from step 2>",
"ClientSecret": "<paste the secret VALUE from step 3>",
"RedirectUri": "https://your-domain.example/api/teams/callback",
"TenantId": "common",
"Scopes": "OnlineMeetings.ReadWrite Calendars.ReadWrite offline_access User.Read"
}
Important notes:
- Keep
TenantIdascommonfor multi-tenant. Set it to a specific tenant Guid only if you want to lock the integration to one organisation. - The
Scopesstring must exactly match the permissions added in step 4 (space-separated). If you add a permission later, update this value AND existing connected users will need to disconnect+reconnect to grant the new scope. The Integrations UI auto-detects this and shows a Reconnect needed banner. - For production, prefer storing
ClientSecretin environment variables or a secret store rather than committing it toappsettings.json. ASP.NET config binding picks upMicrosoftTeams__ClientSecret=...env vars natively.
Step 6 — Recycle and verify
- Recycle the FastLinkIt app pool.
- Sign in to FastLinkIt as any user.
- Navigate to Account → Integrations.
- The Microsoft Teams card should show a Connect Microsoft Teams button (no OAuth not configured warning).
- Click it, sign in, accept consent.
- You should land back on the Integrations page with a green Connected badge.
- Create a test booking on a Teams planner. Within seconds the meeting should appear on your Outlook calendar and the visitor should receive an Outlook invite.
Rotating the client secret
Client secrets expire (max 24 months). To rotate without downtime:
- In Entra ID, generate a NEW client secret with a different description.
- Update
MicrosoftTeams:ClientSecretin your live config. - Recycle the app pool.
- Verify a new connection works.
- Delete the OLD secret in Entra ID.
No user reconnect is needed for a secret rotation — existing refresh tokens stay valid. (Adding or removing scopes is the only operation that requires user reconnect.)
What gets stored in FastLinkIt
For each user who connects Teams, FastLinkIt stores one row in MeetingProviderConnections (Identity database) with:
- The user's FastLinkIt UserId.
- The Provider name (
teams). - The OAuth access token, encrypted at rest with
IDataProtectorusing the purposeMeetingProvider.Tokens.v1. - The encrypted refresh token (same encryption).
- Token expiry timestamp.
- Granted scopes string.
- The user's Microsoft account email (for display in the Integrations UI).
- Created / updated / last-used timestamps.
Disconnecting deletes the row. It does not revoke the OAuth grant on Microsoft's side — to fully revoke, the user can also remove FastLinkIt from their Microsoft consented apps page.
Troubleshooting
Users see OAuth isn't configured on this server yet — The MicrosoftTeams:ClientId / ClientSecret config values are missing or empty. Check appsettings*.json and any environment variable overrides. Recycle the app pool after fixing.
OAuth callback fails with redirect_uri_mismatch — The RedirectUri in appsettings.json doesn't exactly match any redirect URI registered on the Entra ID app. Whitespace, trailing slashes, and http vs https all matter. Update Entra ID to match your config (or vice versa) and recycle.
Meetings created but not appearing on calendar — The connection is missing the Calendars.ReadWrite scope. Either you're running an old version of FastLinkIt (pre-/me/events switch) and need to upgrade, or the user connected before the scope was added and needs to disconnect+reconnect. The Integrations UI shows a banner prompting this.
Personal accounts complete OAuth but every booking returns 403 from Graph — Expected. Microsoft restricts /me/events and /me/onlineMeetings to work/school accounts. The user-facing Integrations UI displays a warning when a connected account email is in a personal Microsoft domain. See the user guide for visitor-facing workarounds.
Adding a new permission later — Edit the app's API permissions in Entra ID, update MicrosoftTeams:Scopes in config, recycle. Existing users get a Reconnect needed banner because their stored Scope field doesn't include the new permission. Adding new-scope detection in the UI is a 5-line change in Integrations.razor (HasCalendarScope-style helper).