Teams SSO Bot Authentication Design Prompt
Implement Single Sign-On (SSO) in a Teams Bot using Entra ID — silent auth, token cache, on-behalf-of for downstream APIs, and graceful fallback.
- Target user
- Backend engineers building Teams bots that need to act as the user against APIs
- Difficulty
- Advanced
- Tools
- Claude, ChatGPT
The prompt
You are a senior backend engineer who has shipped Teams bots with Entra ID SSO to thousands of users, handling token caching, refresh, on-behalf-of flows, and the inevitable edge cases.
I will provide:
- The bot's AAD app registration state (single tenant / multi-tenant)
- Downstream APIs the bot calls (Graph, custom internal APIs, third-party)
- Token lifetime + caching needs
- Compliance + security requirements
Your job:
1. **Why SSO for a Teams bot** — the user is already authenticated to Teams; SSO gets the bot a token without prompting them again. Better UX, fewer abandoned interactions, attributable audit trail.
2. **The Teams SSO flow**:
- User invokes the bot
- Bot sends an `OAuthCard` with the SSO connection name
- Teams obtains a token silently via the user's existing Teams session
- Token is delivered to the bot via a token exchange event
- Bot uses the token to call APIs as the user
3. **AAD app registration setup**:
- **Expose an API** — define an `api://botid-{appid}` Application ID URI
- **Scope** — define `access_as_user` scope
- **Pre-authorized client applications** — add the Teams app id `1fec8e78-bce4-4aaf-ab1b-5451cc387264` and Teams web id `5e3ce6c0-2b1f-4285-8d4b-75ee78787346` (these IDs may change; check Microsoft docs)
- **API permissions** — Graph permissions the bot needs delegated
- **Manifest** — `accessTokenAcceptedVersion: 2`, set the SSO config
4. **Teams app manifest** — `webApplicationInfo`:
```json
"webApplicationInfo": {
"id": "<bot-app-id>",
"resource": "api://botid-<bot-app-id>"
}
```
5. **Token cache strategy**:
- **Per-user, in-memory** — fine for low scale, lost on restart
- **Per-user, distributed** — Redis / Cosmos DB keyed by user oid; encrypted at rest
- **Bot Framework's OAuth Service** — Microsoft manages the cache; easiest; recommended
- Token lifetime: typically 1h; cache slightly less to avoid edge-of-expiry calls
6. **On-Behalf-Of (OBO) flow for downstream APIs**:
- SSO token is for `api://botid-...` — not directly usable for Graph or other APIs
- Use the OBO flow to exchange it for a token to the target API
- Token cache the exchanged tokens separately per (user, target API)
- Refresh independently
7. **Failure modes** — handle gracefully:
- **Consent required** — user hasn't consented to scopes; fall back to interactive sign-in via the `signin/verifyState` flow
- **Token expired during a long operation** — re-acquire silently; retry once
- **Token claims missing** — log + ask user to sign in again
- **MFA required** — bot can't satisfy MFA on the user's behalf; surface a clear "please open Teams and re-auth" message
8. **Multi-tenant** — for multi-tenant bots, the app must be registered as multi-tenant; the Teams admin in each tenant must consent. Document the admin consent URL.
9. **Token validation**:
- Server-side: validate signature against Microsoft signing keys
- Validate `aud` matches your app
- Validate `iss` matches expected tenant(s)
- Validate `nbf` / `exp`
- Never trust client-claimed identity
10. **Audit + observability**:
- Log token acquisitions (success/fail) per user
- Don't log token contents
- Metric: SSO success rate; alert if drops
- User-facing: clear error messages on auth failure, with action ("Open Teams → sign out → sign in")
11. **Compliance overlay** — token storage in regions matching tenant; encryption at rest; retention; CA enforcement (see [Teams Conditional Access for ChatOps](../teams-conditional-access-chatops/)).
Output as: (a) AAD app registration + manifest spec, (b) SSO flow diagram with sequence, (c) token cache design, (d) OBO flow implementation outline, (e) failure-mode handling matrix, (f) token validation checklist, (g) observability + audit schema, (h) multi-tenant considerations.
Bias toward: silent auth where possible, explicit fallback when not, secure token handling, attributable identity for every API call.