Skip to content

feat(msteams): add DefaultAzureCredential auth type for passwordless Teams auth#828

Open
BingqingLyu wants to merge 11 commits intomainfrom
fork-pr-48014-feat-msteams-default-azure-credential
Open

feat(msteams): add DefaultAzureCredential auth type for passwordless Teams auth#828
BingqingLyu wants to merge 11 commits intomainfrom
fork-pr-48014-feat-msteams-default-azure-credential

Conversation

@BingqingLyu
Copy link
Copy Markdown
Owner

@BingqingLyu BingqingLyu commented Apr 27, 2026

Context

Issue openclaw#40855 requested passwordless authentication for the MS Teams channel. PR openclaw#40884 added certificate and federated credential support. PR openclaw#47934 addressed review feedback on that work — fixing schema validation, type design, env var hints, and SDK env fallback handling.

This PR builds on both to add defaultAzureCredential as a fourth auth type, completing the passwordless auth story for enterprise deployments.

Problem

Certificate and federated credential auth modes require operators to explicitly configure credential material (cert paths, FIC client IDs, workload identity assertion files). In Kubernetes deployments with Azure Workload Identity, and in local development with az login, these details are already available in the environment — but the operator still has to know which mode to select and which fields to set.

DefaultAzureCredential from @azure/identity solves this by automatically discovering credentials from the environment: workload identity, managed identity, Azure CLI, environment variables, and other sources. The operator only needs to provide appId and tenantId.

Changes

New auth type: defaultAzureCredential

{
  "channels": {
    "msteams": {
      "enabled": true,
      "appId": "<app-registration-id>",
      "tenantId": "<tenant-id>",
      "authType": "defaultAzureCredential"
    }
  }
}

DefaultAzureCredentialTokenProvider (extensions/msteams/src/sdk.ts)

  • Wraps @azure/identity's DefaultAzureCredential with the same getAccessToken(scope) interface as MsalTokenProvider
  • Passes appId as managedIdentityClientId and workloadIdentityClientId so the credential targets the correct bot identity
  • Normalizes resource URIs to AAD scopes (https://graph.microsoft.comhttps://graph.microsoft.com/.default) since DefaultAzureCredential.getToken() requires scope format, not bare resource URIs

createTokenProvider() factory (extensions/msteams/src/sdk.ts)

  • Returns DAC or MSAL provider based on authType
  • Used by all 4 token acquisition sites: probe.ts, monitor.ts, send-context.ts, graph.ts

Setup surface fix (extensions/msteams/src/setup-surface.ts)

  • When re-entering credentials as client secret via the setup wizard, authType and related fields (certPemFile, certKeyFile, ficClientId, widAssertionFile) are now reset. Previously, re-running setup on a non-client-secret config would preserve the old authType, causing resolveMSTeamsCredentials() to ignore the newly entered secret.

Release checks (extensions/msteams/package.json)

  • Added @azure/identity to rootDependencyMirrorAllowlist so scripts/release-check.ts does not report bundled extension dependency drift.

Config schema + types

  • authType union extended with "defaultAzureCredential" in both types.msteams.ts and zod-schema.providers-core.ts

Use cases

AKS with Workload Identity — the pod's service account has a federated credential. DefaultAzureCredential picks it up automatically. No secrets, no cert files, no Vault.

Local developmentaz login and go. Same config works everywhere.

Azure VMs / App Service — managed identity. Same config.

Dependencies

  • @azure/identity ^4.9.1 added as a dependency of the msteams extension (not root package.json, per plugin guidelines)

AI Disclosure

  • AI-assisted (Claude Code + Codex review — multiple review cycles)
  • Fully tested — 246/246 msteams tests passing
  • pnpm build && pnpm check && pnpm test green (pre-existing normalizeAgentId tsgo error on main excluded)
  • Authors understand what the code does
  • Codex review addressed: scope normalization, identity pinning, setup surface reset, release checks allowlist

Fixes openclaw#40855
Related: openclaw#40884, openclaw#47934

fengyang0317 and others added 11 commits March 16, 2026 01:25
…enclaw#40855)

Add support for alternative authentication methods in the MS Teams
channel, enabling passwordless bot authentication for enterprise
tenants that block client secrets via tenant-wide policy.

New config fields under channels.msteams:
- authType: 'clientSecret' (default) | 'certificate' | 'federatedCredential'
- certPemFile / certKeyFile / sendX5C: for certificate-based auth
- ficClientId: FIC client ID for federated credential auth
- widAssertionFile: workload identity assertion file path

Fully backward compatible: existing appId + appPassword configs
continue to work unchanged.
Test coverage for resolveMSTeamsCredentials and hasConfiguredMSTeamsCredentials
across all three auth types introduced in the preceding commit. Fixed existing
test expectation to include authType field in resolved credentials result.
Verifies certificate auth requires both cert files, federated auth requires
ficClientId or widAssertionFile, and clientSecret is the default authType.
Variable appPassword in MSTeamsCredentials (token.ts) was declared as
required but set to empty string for certificate and federated credential
auth paths. Changed to optional to accurately represent the type contract.
Guarded clientSecret assignment in sdk.ts to handle undefined appPassword.
Added test assertions verifying appPassword is undefined for certificate
and federated credential auth.
Type MSTeamsAuthType in token.ts was a standalone union duplicating the
inline type in MSTeamsConfig.authType (types.msteams.ts). Replaced with
NonNullable<MSTeamsConfig["authType"]> to maintain a single source of
truth. Adding a new auth method now only requires updating types.msteams.ts.
Fields authType, certPemFile, certKeyFile, sendX5C, ficClientId, and
widAssertionFile were added to MSTeamsConfig (types.msteams.ts) but not
to MSTeamsConfigSchema (zod-schema.providers-core.ts). The strict Zod
schema rejected configs using these fields as unrecognized properties.
Added cross-field validation in superRefine: authType "certificate"
requires certPemFile and certKeyFile, authType "federatedCredential"
requires ficClientId or widAssertionFile.
Error messages in errors.ts and probe.ts dropped references to environment
variables MSTEAMS_APP_ID and MSTEAMS_TENANT_ID when the new auth types were
added. Restored env var hints alongside the new auth type guidance so users
configuring via environment variables still get actionable error messages.
Added test assertions verifying env var names appear in auth error hint.
Added presence helpers that check certificate and federated credential
auth material across typed config, SDK plain env vars (certPemFile,
certKeyFile, FICClientId, WIDAssertionFile), and SDK connection env
vars (connections__*__settings__*). Credential resolution and
hasConfiguredMSTeamsCredentials now reject empty configs that have no
auth material in any source, preventing silent fallthrough to managed
identity auth in the SDK. Configs backed by SDK env vars are accepted.
Aligned certificate case in buildMSTeamsAuthConfig with federated case —
only assign certPemFile/certKeyFile to base when present, so undefined
values do not shadow the SDK's env var resolution. Added explicit test
assertions documenting that env-only cert paths are not forwarded in
credentials (SDK merges them at runtime).
New authType "defaultAzureCredential" defers credential selection to
@azure/identity's DefaultAzureCredential, which tries environment
variables, workload identity, managed identity, az cli, and other
sources automatically. Enables passwordless Teams auth in AKS via
workload identity without explicit certificate or secret management.

Added DefaultAzureCredentialTokenProvider in sdk.ts as a drop-in
replacement for MsalTokenProvider. Added createTokenProvider() factory
that returns the appropriate provider based on authType. Updated all
4 call sites (probe, monitor, send-context, graph) to use the factory.

Added @azure/identity as a dependency of the msteams extension.
CloudAdapter.process() acquires outbound tokens via MsalTokenProvider,
which has its own credential chain (WID → FIC → secret → cert → MI).
With defaultAzureCredential, none of these fields were set, causing
fallthrough to ManagedIdentityApplication — which does not support
AKS workload identity federation.

Detect AZURE_FEDERATED_TOKEN_FILE (injected by the workload identity
webhook) and pass it as WIDAssertionFile so the SDK uses its native
WID path. Falls back to @azure/identity DefaultAzureCredential for
environments without workload identity.
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.

[Feature]: Support federated credentials / managed identity for MS Teams Bot Framework authentication

3 participants