feat(msteams): support federated credentials and certificate auth#40884
feat(msteams): support federated credentials and certificate auth#40884fengyang0317 wants to merge 1 commit intoopenclaw:mainfrom
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.
Greptile SummaryThis PR extends the MS Teams channel to support certificate-based and federated credential (workload identity) authentication alongside the existing client-secret flow, enabling enterprise tenants that block client secrets to use the bot without passwords. The changes are additive and fully backward compatible — existing Key observations:
Confidence Score: 4/5
Last reviewed commit: 6774bc8 |
| ): string | undefined { | ||
| if (classification.kind === "auth") { | ||
| return "check msteams appId/appPassword/tenantId (or env vars MSTEAMS_APP_ID/MSTEAMS_APP_PASSWORD/MSTEAMS_TENANT_ID)"; | ||
| return "check msteams appId/tenantId and auth config (appPassword, certificate, or federated credential)"; |
There was a problem hiding this comment.
Env var hints dropped from error message
The updated message removes mention of the MSTEAMS_APP_ID, MSTEAMS_APP_PASSWORD, and MSTEAMS_TENANT_ID environment variables. For users who configure credentials via env vars (rather than the YAML config), this is a regression — they lose the hint pointing to those vars when auth fails.
Consider keeping the env var guidance alongside the new auth type info:
| return "check msteams appId/tenantId and auth config (appPassword, certificate, or federated credential)"; | |
| return "check msteams appId/tenantId and auth config (appPassword, certificate, or federated credential) — or env vars MSTEAMS_APP_ID/MSTEAMS_APP_PASSWORD/MSTEAMS_TENANT_ID"; |
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/msteams/src/errors.ts
Line: 196
Comment:
**Env var hints dropped from error message**
The updated message removes mention of the `MSTEAMS_APP_ID`, `MSTEAMS_APP_PASSWORD`, and `MSTEAMS_TENANT_ID` environment variables. For users who configure credentials via env vars (rather than the YAML config), this is a regression — they lose the hint pointing to those vars when auth fails.
Consider keeping the env var guidance alongside the new auth type info:
```suggestion
return "check msteams appId/tenantId and auth config (appPassword, certificate, or federated credential) — or env vars MSTEAMS_APP_ID/MSTEAMS_APP_PASSWORD/MSTEAMS_TENANT_ID";
```
How can I resolve this? If you propose a fix, please make it concise.| export type MSTeamsCredentials = { | ||
| appId: string; | ||
| appPassword: string; | ||
| tenantId: string; |
There was a problem hiding this comment.
appPassword required but meaningless for non-clientSecret auth
appPassword: string is a required field in MSTeamsCredentials, yet for certificate and federatedCredential auth it's always set to the empty string "". Downstream consumers of this type may be confused by a field that is nominally required but silently unused. Making it optional better represents the actual contract:
| export type MSTeamsCredentials = { | |
| appId: string; | |
| appPassword: string; | |
| tenantId: string; | |
| export type MSTeamsCredentials = { | |
| appId: string; | |
| appPassword?: string; | |
| tenantId: string; | |
| authType: MSTeamsAuthType; | |
| certPemFile?: string; | |
| certKeyFile?: string; | |
| sendX5C?: boolean; | |
| ficClientId?: string; | |
| widAssertionFile?: string; | |
| }; |
The clientSecret branch in sdk.ts already guards the field access with creds.appPassword, so making it optional there is safe. The resolveMSTeamsCredentials return for clientSecret already guarantees a non-empty value via the if (!appPassword) return undefined guard.
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/msteams/src/token.ts
Line: 10-13
Comment:
**`appPassword` required but meaningless for non-`clientSecret` auth**
`appPassword: string` is a required field in `MSTeamsCredentials`, yet for `certificate` and `federatedCredential` auth it's always set to the empty string `""`. Downstream consumers of this type may be confused by a field that is nominally required but silently unused. Making it optional better represents the actual contract:
```suggestion
export type MSTeamsCredentials = {
appId: string;
appPassword?: string;
tenantId: string;
authType: MSTeamsAuthType;
certPemFile?: string;
certKeyFile?: string;
sendX5C?: boolean;
ficClientId?: string;
widAssertionFile?: string;
};
```
The `clientSecret` branch in `sdk.ts` already guards the field access with `creds.appPassword`, so making it optional there is safe. The `resolveMSTeamsCredentials` return for `clientSecret` already guarantees a non-empty value via the `if (!appPassword) return undefined` guard.
How can I resolve this? If you propose a fix, please make it concise.| normalizeSecretInputString, | ||
| } from "./secret-input.js"; | ||
|
|
||
| export type MSTeamsAuthType = "clientSecret" | "certificate" | "federatedCredential"; |
There was a problem hiding this comment.
Duplicated auth type union between token.ts and types.msteams.ts
MSTeamsAuthType is exported from token.ts as a named type, but MSTeamsConfig.authType in src/config/types.msteams.ts repeats the same union inline ("clientSecret" | "certificate" | "federatedCredential"). If a new auth method is added later, both locations need to be updated independently, risking a drift.
I understand types.msteams.ts cannot directly import from token.ts without creating a circular dependency (since token.ts imports MSTeamsConfig). One option is to extract MSTeamsAuthType into its own lightweight file (or into the shared plugin-sdk types) so it can be imported by both sides without a cycle.
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/msteams/src/token.ts
Line: 8
Comment:
**Duplicated auth type union between `token.ts` and `types.msteams.ts`**
`MSTeamsAuthType` is exported from `token.ts` as a named type, but `MSTeamsConfig.authType` in `src/config/types.msteams.ts` repeats the same union inline (`"clientSecret" | "certificate" | "federatedCredential"`). If a new auth method is added later, both locations need to be updated independently, risking a drift.
I understand `types.msteams.ts` cannot directly import from `token.ts` without creating a circular dependency (since `token.ts` imports `MSTeamsConfig`). One option is to extract `MSTeamsAuthType` into its own lightweight file (or into the shared plugin-sdk types) so it can be imported by both sides without a cycle.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6774bc82ef
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| authType?: "clientSecret" | "certificate" | "federatedCredential"; | ||
| /** Path to the certificate PEM file (used when authType is "certificate"). */ | ||
| certPemFile?: string; |
There was a problem hiding this comment.
Add runtime schema entries for new MS Teams auth fields
The new authType/certificate/federated fields are added to MSTeamsConfig here, but MSTeamsConfigSchema is still a strict object that only allows appId, appPassword, tenantId, etc. (src/config/zod-schema.providers-core.ts:1409-1449). In practice, any config that uses channels.msteams.authType, certPemFile, certKeyFile, ficClientId, or widAssertionFile will be rejected as unrecognized keys during config validation, so the feature introduced in this commit cannot be used.
Useful? React with 👍 / 👎.
|
Hi @fengyang0317 — thanks for the submission. I’m the new Microsoft Teams maintainer for OpenClaw. Please give me a day or two to work through the open Teams backlog. Also, join the Twitter community for daily MS Teams feedback + updates: https://x.com/i/communities/2031170403607974228 |
Summary
Adds 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.
Fixes #40855
Changes
New config fields under
channels.msteams:authType:'clientSecret'(default) |'certificate'|'federatedCredential'certPemFile/certKeyFile/sendX5C: for certificate-based authficClientId: FIC client ID for federated credential authwidAssertionFile: workload identity assertion file path (K8s / workload identity)Files changed:
src/config/types.msteams.ts— Added new config type fieldsextensions/msteams/src/token.ts— Updated credential resolution to support all three auth typesextensions/msteams/src/sdk.ts— UpdatedbuildMSTeamsAuthConfigto pass the right fields to the SDK based on auth typeextensions/msteams/src/errors.ts— Updated error hint messageextensions/msteams/src/probe.ts— Updated probe error messageHow it works
The
@microsoft/agents-hostingSDK'sAuthConfigurationalready supportscertPemFile,certKeyFile,FICClientId, andWIDAssertionFile. This PR exposes those capabilities through OpenClaw's config schema.Backward compatibility
Fully backward compatible — existing
appId+appPasswordconfigs continue to work unchanged (defaultauthTypeis'clientSecret').Example configs
Certificate auth:
Federated credential: