Skip to content

feat(apps): add multi-flow OAuth lifecycle - #744

Open
Mehak Bindra (MehakBindra) wants to merge 15 commits into
mainfrom
mehakbindra-oauth-lifecycle
Open

feat(apps): add multi-flow OAuth lifecycle#744
Mehak Bindra (MehakBindra) wants to merge 15 commits into
mainfrom
mehakbindra-oauth-lifecycle

Conversation

@MehakBindra

@MehakBindra Mehak Bindra (MehakBindra) commented Aug 21, 2026

Copy link
Copy Markdown
Member

Summary

Adds a first-class, per-connection OAuth lifecycle to @microsoft/teams.apps, modeled on microsoft/teams.net and using the turn-state support from #729.

  • adds OAuthFlow for silent token lookup, interactive sign-in, sign-out, and completion/failure callbacks
  • supports AppOptions.oauthFlows, app.addOAuthFlow(...), and app.getOAuthFlow(...)
  • routes token exchange, verify-state, and sign-in failure invokes across multiple connections
  • persists pending attribution and exchange deduplication in turn state, with bounded process-local fallback when state is disabled
  • adds ctx.getConnectionStatus(), including direct token checks that correct stale silent-SSO status results
  • handles channel/group-chat OAuth cards consistently with Teams SSO behavior
  • replaces the Graph-only example with a Graph and GitHub OAuth example

Public API

const app = new App({ oauthFlows: ['graph', 'github'] });
const graph = app.getOAuthFlow('graph');

graph
  .onSignInComplete(async (ctx, token) => { /* use token */ })
  .onSignInFailure(async (ctx, failure) => { /* handle failure */ });

const token = await graph.signIn(ctx);
await graph.signOut(ctx);
const statuses = await ctx.getConnectionStatus();

Compatibility and behavior

  • retains existing OAuth settings, context helpers, events, routes, response shapes, explicit legacy connection overrides, and the TypeScript sign-in activity override
  • registered flows do not enable eager per-turn token lookup
  • omitted state is enabled internally for registered flows; explicit state: false keeps bounded process-local tracking
  • expected token misses (400, 404, 412) trigger interactive fallback; unexpected service or transport failures propagate
  • verify-state continues only for connection misses; unexpected HTTP failures preserve their status
  • successful exchanges are marked processed before callbacks, so retries remain deduplicated if a callback throws

Breaking changes

  • ctx.signin() previously treated every token lookup failure as a missing token and sent an OAuth card. It now sends a card only for expected token-miss responses (400, 404, 412). Unexpected service and transport failures propagate and may produce a 500 for the turn instead of silently switching to interactive sign-in.
  • OAuth invoke spans are unified under microsoft.teams.oauth, with oauth.operation distinguishing token exchange, verification, and failure. Existing oauth.result values also move to lifecycle-specific values. Dashboards and alerts using the previous span names or result values must migrate; this must be called out in the release changelog. The non-HTTP error value remains exception.

Comment thread packages/apps/src/oauth/registry.ts
Comment thread packages/apps/src/oauth/handlers.ts Outdated
Comment thread packages/apps/src/app.ts Outdated
Comment thread packages/apps/src/oauth/handlers.ts Outdated
Comment thread packages/apps/src/oauth/index.ts Outdated
Comment thread packages/apps/src/oauth/handlers.ts
Comment thread packages/apps/src/oauth/handlers.ts Outdated
Comment thread packages/apps/src/oauth/index.ts Outdated
Comment thread packages/apps/src/diagnostics/constants.ts
Comment thread packages/apps/src/app.ts Outdated
@MehakBindra
Mehak Bindra (MehakBindra) force-pushed the mehakbindra-oauth-lifecycle branch 5 times, most recently from c5fa1a2 to d372ac6 Compare August 25, 2026 21:05
Comment thread packages/apps/src/contexts/activity.ts
@MehakBindra
Mehak Bindra (MehakBindra) force-pushed the mehakbindra-oauth-lifecycle branch 3 times, most recently from 3f7dc77 to 18b6163 Compare August 26, 2026 00:39
Base automatically changed from mehakbindra-add-per-turn-state to main August 26, 2026 23:14
Add per-connection OAuth flows, lifecycle callbacks, multi-flow invoke routing, pending attribution, exchange deduplication, telemetry, compatibility fallbacks, and the OAuth example.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Validate deprecated context sign-in connections before initiation, record pending attribution for the selected flow, expose the completed connection on signin events, and keep internal OAuth helpers out of the package barrel.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Treat the implicit default as a normal flow, standardize completion error semantics, and preserve plugin-provided context in OAuth lifecycle callback types.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Automatically enable turn state for explicit OAuth flows, reject state: false, store pending attribution and bounded exchange deduplication in state, and require exact token-exchange routing.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Copilot AI lite review requested due to automatic review settings August 26, 2026 23:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a first-class multi-connection OAuth lifecycle to @microsoft/teams.apps, introducing a per-connection OAuthFlow API (token lookup, interactive sign-in/out, status, and callbacks) while preserving legacy ctx.signin()/ctx.signout() compatibility paths with stricter error handling and optional state-backed deduplication/attribution.

Changes:

  • Introduces OAuthFlow, OAuthFlowRegistry, and default invoke handlers to route signin/tokenExchange, signin/verifyState, and signin/failure across multiple registered connections with telemetry and deduplication.
  • Integrates OAuth-flow-driven pending attribution + exchange deduplication with per-turn state (auto-enabled when flows are registered unless state: false).
  • Replaces the prior Graph-only example with a multi-provider OAuth example (Graph + GitHub) and updates exports/public options layout.

Reviewed changes

Copilot reviewed 26 out of 33 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
README.md Updates examples list to point to the new OAuth sample.
packages/apps/src/state/loader.ts Adds an OAuth-specific state loader helper and centralizes LocalStorage warnings.
packages/apps/src/oauth/telemetry.ts New OAuth operation tracing + metrics/attributes recording helpers.
packages/apps/src/oauth/registry.ts New registry for legacy-default vs multi-flow mode + installs invoke routes.
packages/apps/src/oauth/index.ts Implements OAuthFlow lifecycle API and shared sign-in helper; keeps legacy OAuth settings.
packages/apps/src/oauth/handlers.ts New multi-flow invoke handlers for token exchange, verify-state, and signin failure routing.
packages/apps/src/oauth/handlers.spec.ts Updates/extends handler tests for multi-flow routing, dedupe, attribution, and telemetry.
packages/apps/src/oauth/flow.spec.ts Adds focused tests for OAuthFlow lifecycle behavior and telemetry.
packages/apps/src/oauth.ts Removes legacy standalone OAuth settings module (moved under oauth/).
packages/apps/src/index.ts Re-exports new OAuthFlow surfaces and types from the package entrypoint.
packages/apps/src/diagnostics/constants.ts Consolidates OAuth span name and expands OAuth operation/result constants.
packages/apps/src/contexts/activity.ts Refactors deprecated signin() helper to use shared OAuth sign-in logic + flow validation hooks.
packages/apps/src/contexts/activity.test.ts Updates tests for new signin error semantics and pending attribution hooks.
packages/apps/src/app.ts Wires OAuthFlowRegistry, declarative oauthFlows, and OAuth-driven state enabling into App.
packages/apps/src/app.spec.ts Adds App-level tests for flow registration, case-insensitive lookup, and state behavior.
packages/apps/src/app.process.ts Switches to getStateLoader() so state can become available after OAuth flow registration.
packages/apps/src/app.process.spec.ts Adds coverage for state enablement + legacy helper validation under registered flows.
packages/apps/src/app.plugin.spec.ts Verifies plugin-provided context fields flow through OAuth lifecycle callbacks.
packages/apps/src/app.options.ts Extracts AppOptions (and related types) into a dedicated module and adds oauthFlows.
packages/apps/src/app.oauth.ts Removes legacy single-flow OAuth handlers implementation (replaced by new flow system).
package-lock.json Updates workspace deps and adds new example package; contains lockfile churn/stale workspace entry.
examples/oauth/turbo.json Adds Turbo build task config for the new OAuth example.
examples/oauth/tsconfig.json Adds TS build config for the OAuth example.
examples/oauth/src/index.ts New OAuth sample demonstrating Graph + GitHub flows and callbacks.
examples/oauth/README.md Updates sample docs for multi-provider OAuth setup and commands.
examples/oauth/package.json Renames example package to @examples/oauth and adds Graph client dependency.
examples/oauth/eslint.config.js Adds ESLint config wiring for the new example.
examples/oauth/CHANGELOG.md Renames changelog header to match new example package name.
examples/oauth/appPackage/outline.png Adds new example app assets (LFS pointers).
examples/oauth/appPackage/manifest.json Updates manifest name/description to match multi-provider OAuth example.
examples/oauth/appPackage/color.png Adds new example app assets (LFS pointers).
examples/oauth/.gitignore Adds example-local ignores for Teams tooling and build artifacts.
examples/graph/src/index.ts Removes the old Graph-only example entrypoint.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/apps/src/oauth/registry.ts
Comment thread packages/apps/src/oauth/handlers.ts
Comment thread examples/oauth/src/index.ts
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Comment thread README.md Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Retain the existing Graph example and direct multi-connection users to the OAuthFlow sample.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0d88953d-cdee-4a28-ac2d-36a5fee72da5
Comment thread examples/oauth/src/index.ts
Comment thread packages/apps/src/oauth.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants