feat(msteams): add DefaultAzureCredential auth type for passwordless Teams auth#828
Open
BingqingLyu wants to merge 11 commits intomainfrom
Open
feat(msteams): add DefaultAzureCredential auth type for passwordless Teams auth#828BingqingLyu wants to merge 11 commits intomainfrom
BingqingLyu wants to merge 11 commits intomainfrom
Conversation
…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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
defaultAzureCredentialas 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.DefaultAzureCredentialfrom@azure/identitysolves this by automatically discovering credentials from the environment: workload identity, managed identity, Azure CLI, environment variables, and other sources. The operator only needs to provideappIdandtenantId.Changes
New auth type:
defaultAzureCredential{ "channels": { "msteams": { "enabled": true, "appId": "<app-registration-id>", "tenantId": "<tenant-id>", "authType": "defaultAzureCredential" } } }DefaultAzureCredentialTokenProvider(extensions/msteams/src/sdk.ts)@azure/identity'sDefaultAzureCredentialwith the samegetAccessToken(scope)interface asMsalTokenProviderappIdasmanagedIdentityClientIdandworkloadIdentityClientIdso the credential targets the correct bot identityhttps://graph.microsoft.com→https://graph.microsoft.com/.default) sinceDefaultAzureCredential.getToken()requires scope format, not bare resource URIscreateTokenProvider()factory (extensions/msteams/src/sdk.ts)authTypeprobe.ts,monitor.ts,send-context.ts,graph.tsSetup surface fix (
extensions/msteams/src/setup-surface.ts)authTypeand related fields (certPemFile,certKeyFile,ficClientId,widAssertionFile) are now reset. Previously, re-running setup on a non-client-secret config would preserve the oldauthType, causingresolveMSTeamsCredentials()to ignore the newly entered secret.Release checks (
extensions/msteams/package.json)@azure/identitytorootDependencyMirrorAllowlistsoscripts/release-check.tsdoes not report bundled extension dependency drift.Config schema + types
authTypeunion extended with"defaultAzureCredential"in bothtypes.msteams.tsandzod-schema.providers-core.tsUse cases
AKS with Workload Identity — the pod's service account has a federated credential.
DefaultAzureCredentialpicks it up automatically. No secrets, no cert files, no Vault.Local development —
az loginand 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 rootpackage.json, per plugin guidelines)AI Disclosure
pnpm build && pnpm check && pnpm testgreen (pre-existingnormalizeAgentIdtsgo error on main excluded)Fixes openclaw#40855
Related: openclaw#40884, openclaw#47934