Skip to content

feat(msteams): add federated credential support (certificate + managed identity)#53615

Open
HDYA wants to merge 24 commits intoopenclaw:mainfrom
HDYA:hdya/teams-authentications
Open

feat(msteams): add federated credential support (certificate + managed identity)#53615
HDYA wants to merge 24 commits intoopenclaw:mainfrom
HDYA:hdya/teams-authentications

Conversation

@HDYA
Copy link
Copy Markdown

@HDYA HDYA commented Mar 24, 2026

Add alternative authentication methods for Microsoft Teams beyond client secrets. Users can now authenticate using:

  • Certificate-based auth (PEM file via ClientCertificateCredential)
  • Azure Managed Identity (system- or user-assigned via ManagedIdentityCredential)

Changes:

  • MSTeamsCredentials is now a discriminated union with type: "secret" | "federated"
  • createMSTeamsApp dispatches by credential type:
    • secret: clientId + clientSecret (existing behavior, fully backward compatible)
    • certificate: reads PEM, uses ClientCertificateCredential from @azure/identity with a custom token callback
    • managed identity: uses ManagedIdentityCredential from @azure/identity with a custom token callback
  • MSTeamsConfig type gains 5 new optional fields: authType, certificatePath, certificateThumbprint, useManagedIdentity, managedIdentityClientId
  • Zod schema updated with new optional fields (runtime credential resolver handles cross-field validation)
  • 5 new env vars: MSTEAMS_AUTH_TYPE, MSTEAMS_CERTIFICATE_PATH, MSTEAMS_CERTIFICATE_THUMBPRINT, MSTEAMS_USE_MANAGED_IDENTITY, MSTEAMS_MANAGED_IDENTITY_CLIENT_ID
  • Tests updated for all auth paths (25 total: 18 token + 7 sdk)
  • @azure/identity added as dependency (dynamically imported at runtime for federated auth flows only)
  • Also bumps @microsoft/teams.apps and @microsoft/teams.api to 2.0.6

Summary

  • Problem: MS Teams bot integration only supports client secret authentication, which is unsuitable for production environments requiring certificate-based or managed identity auth (e.g., AKS workload identity).
  • Why it matters: Enterprise deployments need passwordless auth. Azure recommends managed identity or certificate over client secrets for service-to-service auth.
  • What changed: MSTeamsCredentials is now a discriminated union (secret | federated). New createFederatedApp, createCertificateApp, and createManagedIdentityApp factory functions dispatch based on credential type. Credential instances are lazily created and cached for token reuse. Zod schema extended with optional fields.
  • What did NOT change: Existing appId + appPassword + tenantId secret-based auth path is untouched. Default behavior (no authType configured) resolves to "secret" — fully backward compatible.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Root Cause / Regression History (if applicable)

N/A — this is a new feature, not a bug fix.

Regression Test Plan (if applicable)

  • Coverage level:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test files: extensions/msteams/src/sdk.test.ts, extensions/msteams/src/token.test.ts
  • Scenarios locked in:
    • Secret credentials pass clientId/clientSecret/tenantId to SDK (backward compat)
    • Certificate credentials read PEM file and use ClientCertificateCredential for token acquisition
    • Managed identity credentials use ManagedIdentityCredential with lazy caching
    • System-assigned and user-assigned MI both covered
    • Token acquisition failure throws descriptive error
    • Missing certificatePath + no managedIdentity throws
    • Env var resolution for all new fields
    • Discriminated union type resolution (secret vs federated)
    • Config useManagedIdentity: false overrides env MSTEAMS_USE_MANAGED_IDENTITY=true
  • Why this is the smallest reliable guardrail: Unit tests cover each code path through the credential factory without requiring Azure infrastructure
  • 25 tests total (18 token + 7 sdk), all passing

User-visible / Behavior Changes

  • New optional config fields: authType, certificatePath, certificateThumbprint, useManagedIdentity, managedIdentityClientId
  • New env vars: MSTEAMS_AUTH_TYPE, MSTEAMS_CERTIFICATE_PATH, MSTEAMS_CERTIFICATE_THUMBPRINT, MSTEAMS_USE_MANAGED_IDENTITY, MSTEAMS_MANAGED_IDENTITY_CLIENT_ID
  • Default behavior unchanged — existing appId + appPassword configs continue working without modification

Security Impact (required)

  • New permissions/capabilities? Yes — adds managed identity and certificate auth paths
  • Secrets/tokens handling changed? Yes — new token acquisition via @azure/identity (ManagedIdentityCredential for MI, ClientCertificateCredential for certs)
  • New/changed network calls? Yes — managed identity flow calls Azure IMDS (169.254.169.254) and AAD token endpoint
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • Risk + mitigation: Certificate private key is read from a file path (not embedded in config). Managed identity tokens are scoped per SDK request. @azure/identity handles token caching and refresh. No secrets are logged.

Repro + Verification

Environment

  • OS: Linux (container on AKS)
  • Runtime: Node.js
  • Integration/channel: Microsoft Teams
  • Relevant config: authType: "federated", useManagedIdentity: true with AKS workload identity

Steps

  1. Configure msteams with authType: "federated" and useManagedIdentity: true
  2. Ensure pod service account has federated identity credential linked to Entra app
  3. Send message to bot in Teams

Expected

  • Bot authenticates via managed identity token and responds

Actual

  • Pending E2E verification in a pod running on AKS with federated credential

Evidence

  • Failing test/log before + passing after
  • All 357 msteams tests pass after rebase with main
  • 25 new tests specifically covering federated auth paths

Human Verification (required)

  • Verified scenarios: All unit tests pass for secret, certificate, and managed identity auth paths
  • Edge cases checked: Missing cert path, system vs user-assigned MI, token acquisition failure, useManagedIdentity: false overriding env var
  • What was not verified: Full E2E flow in a pod running on AKS with federated credential (planned as follow-up)

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? YesresolveAuthType() defaults to "secret" when not configured
  • Config/env changes? Yes — 5 new optional config fields, 5 new env vars (all optional)
  • Migration needed? No — existing configurations work without changes

Failure Recovery (if this breaks)

  • How to disable/revert: Remove authType from config (defaults back to secret auth)
  • Files/config to restore: Only msteams config section
  • Known bad symptoms: "Failed to acquire token" error in logs if managed identity is misconfigured

Risks and Mitigations

  • Risk: @azure/identity adds transitive dependencies to the package
    • Mitigation: Only imported dynamically at runtime when federated auth is actually configured; does not affect secret-based deployments
  • Risk: Managed identity requires correct Azure infrastructure (federated credential, OIDC issuer)
    • Mitigation: Descriptive error messages when token acquisition fails; documented setup requirements

@openclaw-barnacle openclaw-barnacle bot added channel: msteams Channel integration: msteams size: L docs Improvements or additions to documentation labels Mar 24, 2026
@HDYA HDYA marked this pull request as ready for review March 25, 2026 11:39
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c3c8dfa94a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 25, 2026

Greptile Summary

This PR adds certificate and Azure Managed Identity authentication paths to the MS Teams integration by refactoring MSTeamsCredentials into a discriminated union ("secret" | "federated") and introducing corresponding factory functions. The config type, Zod schema, token.ts, and tests are all well-structured, and the default "secret" path is fully backward-compatible.

Key findings:

  • P1 — Managed identity token cache bypassed: createManagedIdentityApp allocates a new ManagedIdentityCredential / DefaultAzureCredential instance on every invocation of tokenProvider. Each @azure/identity credential object maintains its own in-memory token cache; recreating the instance on every call discards the cache and triggers a fresh Azure IMDS or AAD token request per Teams message. Under load this will hit IMDS rate limits. The credential should be created once and captured in the closure.
  • P2 — readFileSync error lacks context: Missing/unreadable certificate files surface as raw ENOENT/EACCES errors. A wrapping try/catch with a descriptive message would significantly improve operator experience.
  • P2 — createMSTeamsAdapter test coverage dropped: The previous test verifying deleteActivity via continueConversation proactive sends was removed and not replaced. createSendContext (used by continueConversation) still wires up deleteActivity via REST, but this path now has no unit test coverage.

Confidence Score: 3/5

  • Safe to merge for secret-auth users; the managed identity path has a token-caching bug that will cause IMDS rate-limit pressure under production load.
  • The discriminated union refactor, Zod validation, config types, and token.ts logic are all solid. The managed identity credential-recreation issue (P1) is a genuine production reliability concern for the new auth path — every message that requires a token refresh will make a fresh IMDS call rather than reusing a cached token. The fix is small (hoist credential construction outside tokenProvider). The P2 items (readFileSync error handling, adapter test gap) are non-blocking but worth addressing.
  • extensions/msteams/src/sdk.ts — specifically createManagedIdentityApp (lines 97–122)
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/msteams/src/sdk.test.ts
Line: 141

Comment:
**`createMSTeamsAdapter` + `continueConversation` test coverage dropped**

The previous `sdk.test.ts` contained a test titled `"provides deleteActivity in proactive continueConversation contexts"` that verified an HTTP `DELETE` was issued via `ctx.deleteActivity` inside the `logic` callback. That test — and the whole import of `createMSTeamsAdapter` — was removed in this PR and not replaced.

`createSendContext` (used by `continueConversation`) still wires up `deleteActivity` via `deleteActivityViaRest`, so the production code path still exists. A coverage gap now exists for the `continueConversation` proactive messaging flow. Consider adding at minimum one test that exercises `createMSTeamsAdapter.continueConversation` and verifies `sendActivity` / `deleteActivity` behavior against a `fetch` mock.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/msteams/src/sdk.ts
Line: 101-115

Comment:
**Credential instance recreated on every token call — token cache never reused**

`tokenProvider` creates a brand-new `ManagedIdentityCredential` / `DefaultAzureCredential` instance on every invocation. Each `@azure/identity` credential object maintains its own in-memory token cache; constructing a fresh instance discards that cache, so every call to `tokenProvider` issues a new outbound token request to Azure IMDS or AAD — even when the previous token is still valid.

Under realistic load (one Teams message → one `tokenProvider` call), this results in a new IMDS/AAD round-trip per message. IMDS is rate-limited, and `DefaultAzureCredential` probes multiple credential sources in sequence on each construction, making the overhead significant.

The credential should be created once (lazily, to keep the dynamic import on-demand) and captured in the closure — a module-level promise variable initialised on first call is the standard pattern for this in `@azure/identity` users. Something like:

```typescript
let credentialPromise: Promise<ManagedIdentityCredential | DefaultAzureCredential> | null = null;

const getCredential = async () => {
  if (!credentialPromise) {
    credentialPromise = import("@azure/identity").then((az) =>
      creds.managedIdentityClientId
        ? new az.ManagedIdentityCredential(creds.managedIdentityClientId)
        : new az.DefaultAzureCredential(),
    );
  }
  return credentialPromise;
};

const tokenProvider = async (): Promise<string> => {
  const credential = await getCredential();
  const token = await credential.getToken(BOT_FRAMEWORK_SCOPE);
  if (!token?.token) throw new Error("Failed to acquire token via managed identity.");
  return token.token;
};
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/msteams/src/sdk.ts
Line: 85

Comment:
**Unguarded `readFileSync` surfaces raw filesystem errors**

If `creds.certificatePath` points to a missing or unreadable file, Node.js throws a raw `ENOENT`/`EACCES` error with no context about certificate-based auth. Wrapping the call in a try/catch and re-throwing with a descriptive message (e.g. `"Failed to read certificate file at '${creds.certificatePath}': ${err.message}"`) would produce a much clearer diagnostic for operators configuring this for the first time.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "Merge origin/main into hdya/teams-authen..." | Re-trigger Greptile

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5a763a2493

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7faecd5659

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@HDYA HDYA force-pushed the hdya/teams-authentications branch from 7faecd5 to 3f09bf8 Compare March 25, 2026 12:37
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3f09bf808b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e16c60c86

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@HDYA HDYA force-pushed the hdya/teams-authentications branch from 7e16c60 to dbb0fb2 Compare March 25, 2026 13:59
@HDYA
Copy link
Copy Markdown
Author

HDYA commented Mar 25, 2026

it appears that the MAC OS check error is from main branch

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3ccbc9d5e9

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@HDYA HDYA force-pushed the hdya/teams-authentications branch from 3ccbc9d to f9cd5ea Compare March 25, 2026 17:20
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f9cd5eafdd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@HDYA HDYA force-pushed the hdya/teams-authentications branch from f9cd5ea to 718220a Compare March 25, 2026 17:37
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 718220abb3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 802ea3e9ee

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@HDYA HDYA force-pushed the hdya/teams-authentications branch from 802ea3e to 25279e4 Compare March 27, 2026 14:57
@openclaw-barnacle openclaw-barnacle bot added the docs Improvements or additions to documentation label Mar 27, 2026
@HDYA HDYA force-pushed the hdya/teams-authentications branch from 25279e4 to 698f758 Compare March 27, 2026 17:43
@HDYA HDYA force-pushed the hdya/teams-authentications branch from 192937e to 145def1 Compare April 2, 2026 02:29
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 145def140c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a9db007103

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@HDYA HDYA force-pushed the hdya/teams-authentications branch from b5c2006 to 4e8541c Compare April 3, 2026 01:27
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4e8541c6eb

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

pnpm-lock.yaml Outdated
Comment on lines +203 to +205
'@typescript/native-preview':
specifier: 7.0.0-dev.20260401.1
version: 7.0.0-dev.20260401.1
specifier: 7.0.0-dev.20260331.1
version: 7.0.0-dev.20260331.1
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep native-preview lock specifier aligned with package.json

The root lockfile now pins @typescript/native-preview to 7.0.0-dev.20260331.1, but package.json in this same commit still requires 7.0.0-dev.20260401.1; with CI running pnpm install --frozen-lockfile in .github/workflows/ci.yml, this mismatch will fail dependency installation before tests/build. Fresh evidence in this commit is the changed root importer entry at pnpm-lock.yaml now using the older dev build number.

Useful? React with 👍 / 👎.

Comment on lines +307 to +311
expect(appInstances[0]).toEqual({
clientId: "my-app-id",
clientSecret: "my-secret",
tenantId: "my-tenant",
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Update secret-app test assertion for injected plugin field

createMSTeamsApp now always injects a no-op HTTP plugin, so the captured constructor options include a plugins property; this test uses strict toEqual with only clientId/clientSecret/tenantId, which makes the new case fail even when behavior is correct. Running this test file will produce a deterministic false negative until the assertion is relaxed (for example toMatchObject) or includes plugins.

Useful? React with 👍 / 👎.

HDYA and others added 23 commits April 3, 2026 02:11
…d identity)

Add alternative authentication methods for Microsoft Teams beyond client
secrets. Users can now authenticate using:

- Certificate-based auth (PEM file + thumbprint)
- Azure Managed Identity (system- or user-assigned)

Changes:
- MSTeamsCredentials is now a discriminated union with type: 'secret' | 'federated'
- createMSTeamsApp dispatches by credential type:
  - secret: clientId + clientSecret (existing behavior, fully backward compatible)
  - certificate: reads PEM, passes clientCertificate to SDK App constructor
  - managed identity: dynamically imports @azure/identity for tokenProvider
- MSTeamsConfig type gains 5 new optional fields: authType, certificatePath,
  certificateThumbprint, useManagedIdentity, managedIdentityClientId
- Zod schema updated with new fields + cross-field validation in superRefine
- 6 new env vars: MSTEAMS_AUTH_TYPE, MSTEAMS_CERTIFICATE_PATH,
  MSTEAMS_CERTIFICATE_THUMBPRINT, MSTEAMS_USE_MANAGED_IDENTITY,
  MSTEAMS_MANAGED_IDENTITY_CLIENT_ID
- Tests updated for all auth paths (21 total: 14 token + 7 sdk)
- No new npm dependencies (@azure/identity is dynamically imported)
…azure/identity dep

The Teams SDK App constructor expects 'token' for custom token factories,
not 'tokenProvider'. This caused the SDK to ignore the custom credential
resolution (DefaultAzureCredential/WorkloadIdentityCredential) and fall
back to its internal ManagedIdentityApplication via IMDS, which fails on
AKS workload identity.

Also adds @azure/identity as a production dependency so the dynamic
import resolves at runtime.
Bump @microsoft/teams.apps from 2.0.5 to 2.0.6. v2.0.6 removes the
problematic /api* wildcard route pattern incompatible with Express 5.
This eliminates the need for the sed workaround in the AKSclaw
Dockerfile (commit 705b855).

Fix sdk.test.ts: rename .tokenProvider to .token to match sdk.ts
property name, use vi.hoisted for @azure/identity mock constructors.
All 350 msteams tests pass.
Add comprehensive docs for certificate-based and managed identity
authentication:
- New section: Federated Authentication (Certificate + Managed Identity)
- Option A: Certificate-based auth with PEM file
- Option B: Azure Managed Identity (system/user-assigned)
- AKS Workload Identity setup guide with step-by-step instructions
- Auth type comparison table
- New config keys and env vars documented
- Quick setup updated to reference federated auth
Auto-formatted by oxfmt to pass CI check.
Addresses review feedback and fixes implementation bugs:

- P1: Hoist credential instances outside tokenProvider into a lazily-
  initialized cached promise, so @azure/identity token cache is reused
  across messages instead of creating fresh credential per call.
- P1: System-assigned MI now uses ManagedIdentityCredential() instead
  of DefaultAzureCredential to avoid unintended auth source probing.
- P1: Certificate auth now uses ClientCertificateCredential via token
  function instead of non-existent clientCertificate SDK option that
  was silently ignored at runtime.
- P2: Wrap readFileSync in try/catch with descriptive error message
  when certificate file is missing or unreadable.
- Fix: Token function signature now accepts (scope, tenantId?) to
  match SDK's TokenCredentials['token'] contract.
- Fix: All TypeScript type errors resolved (add Client to test fake
  SDK, work around tsgo AppOptions narrowing).
The superRefine block rejected authType=federated when appId, tenantId,
or certificatePath/useManagedIdentity were absent from the config object,
but these fields can legitimately come from MSTEAMS_* environment variables.
This blocked env-var-only deployments (a common secret-management pattern).

Runtime validation in resolveMSTeamsCredentials() already handles the
field resolution and returns undefined when config is incomplete.
Use nullish coalescing (??) instead of logical OR (||) so that an
explicit config value of false is respected over the MSTEAMS_USE_
MANAGED_IDENTITY environment variable. Previously, a federated config
that set useManagedIdentity: false with certificatePath would still
resolve to managed identity if the env var was true.
…quired

Certificate auth now uses @azure/identity ClientCertificateCredential
which extracts the thumbprint from the PEM content automatically.
Remove the mandatory thumbprint step from setup instructions and mark
the certificateThumbprint config field as optional.
Address greptile P2 review comment: the previous deleteActivity +
continueConversation test was removed during the SDK refactor.

Add tests for:
- continueConversation sendActivity (REST API client)
- continueConversation deleteActivity (REST DELETE)
- Missing serviceUrl / conversation.id validation
- process() 200 response for message activities
- process() immediate 200 for invoke activities
Vitest hoisting can transform function declarations inside vi.mock
factories into arrow functions, which cannot be used with `new`.
Switch to class syntax to ensure constructors work after hoisting.

Also regenerate config docs baseline after rebase with main.
Snapshot MSTEAMS_* env vars before clearing and restore original values in teardown, preventing state leaks across suites in shared-process mode.
Federated certificate and managed-identity branches now receive the noOpHttp plugin, preventing Express 5 path-to-regexp incompatibility from the default Teams HTTP plugin.
@HDYA HDYA force-pushed the hdya/teams-authentications branch from 4e8541c to 30f4a03 Compare April 3, 2026 02:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: msteams Channel integration: msteams docs Improvements or additions to documentation size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant