Skip to content

Introduce MSAL with UMI and FIC support#387

Merged
heyitsaamir merged 29 commits into
mainfrom
aamirj/addMsal
Nov 12, 2025
Merged

Introduce MSAL with UMI and FIC support#387
heyitsaamir merged 29 commits into
mainfrom
aamirj/addMsal

Conversation

@heyitsaamir

@heyitsaamir heyitsaamir commented Nov 6, 2025

Copy link
Copy Markdown
Collaborator

This PR introduces MSAL as a dependency and switches our supported bot authentication to use it. It also includes support for User Managed Identity support and FIC such that we don't need to provide custom code to do that anymore as we had previously suggested. Instead, we can do that simply by the environment variables.

CLIENT_ID CLIENT_SECRET MANAGED_IDENTITY_CLIENT_ID Output
not_set No-Auth
set set SecretsAuth
set not_set User Managed Identity Auth
set not_set set (same as CLIENT_ID) User Managed Identity Auth
set not_set set (diff from CLIENT_ID) FIC (user managed identity)
set not_set "system" FIC (system identity)

Changes to note:

  1. We are now no longer proactively refreshing tokens. Instead, we put the token fetcher inside the token resolver logic for the client. This ends up being a call to tokenManager.getBotToken.
  2. This fixes a bug where proactive scenarios were going to fail because we weren't refreshing the token for them. For reactive scenarios, we refresh the token when the request comes in, so it was fine.
  3. We are deprecating the id and name fields because those used to depend on the token being present. Now that we are not proactively fetching the token, those are not as useful (or reliable). For now, I have chosen to simply use the value from the manifest to populate them. I don't think these fields were that useful anyway, so opting to deprecate.
  4. Removes graphToken from being injected into plugins. Plugins weren't using it, and we want to remove tight dependency on graph package.

PR Dependency Tree

This tree was auto-generated by Charcoal

rido-min
rido-min previously approved these changes Nov 11, 2025
@heyitsaamir heyitsaamir changed the title Introduce MSAL Introduce MSAL with UMI and FIC support Nov 11, 2025
lilyydu
lilyydu previously approved these changes Nov 11, 2025
Comment thread packages/api/src/clients/bot/token.ts Outdated
@heyitsaamir
heyitsaamir merged commit c26ad56 into main Nov 12, 2025
9 checks passed
@heyitsaamir
heyitsaamir deleted the aamirj/addMsal branch November 12, 2025 00:00
heyitsaamir added a commit that referenced this pull request Nov 17, 2025
I added `type: 'clientSecrets'` and `type: 'token'` in #387 . Looks like
ATK is using `TokenCredentials` directly which breaks since they don't
provide the value of `type` by default. In this PR, I am removing those
type fields and inferring them from the actual values.

skip-test-verification
heyitsaamir added a commit that referenced this pull request Dec 9, 2025
In v2.0.3, `app.name` was changed from reading
`tokens.bot?.appDisplayName` to `manifest.name?.full`. The `send()`
method's validation check `if (!this.id || !this.name)` now throws "app
not started" when `manifest.name` is not provided, even when the app has
started successfully.

## Changes

- **Removed `!this.name` validation** in `send()` method - only
`!this.id` is required
- **Fallback to app ID for bot name** when `manifest.name` is undefined
(`name: this.name || this.id`)
- **Added tests** covering send with/without manifest.name, and proper
error when app ID is missing

## Example

```typescript
// This now works without requiring manifest.name
const app = new App({
  clientId: "...",
  clientSecret: "...",
  tenantId: "...",
  // No manifest.name needed
});

await app.start();
await app.send(conversationId, "Hello"); // ✓ Works (uses app ID as bot name)
```

The `app.name` getter is already marked `@deprecated` and should not be
used for validation.

<!-- START COPILOT CODING AGENT SUFFIX -->



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>[Bug]: Misleading "app not started" error when
manifest.name is not configured (breaking change in
v2.0.3)</issue_title>
> <issue_description>### Bug Description
> 
> After upgrading from `@microsoft/teams.apps` v2.0.2 to v2.0.4, calls
to `app.send()` fail with the error `"app not started"` even though the
>   app has successfully started.
> 
> The root cause is a breaking change introduced in [PR
#387](#387)
(released in v2.0.3). The
> `app.name` getter was changed from reading the bot's display name from
tokens to reading from the `manifest.name` constructor option:
> 
> **Before (v2.0.2)** - [`app.ts`
L136-L138](https://github.com/microsoft/teams.ts/blob/ece19d488f7975b11f702676b1c6b02e692f66e0/packages/apps/src/app.ts#L136-L138):
>   ```typescript
>   get name() {
>     return this.tokens.bot?.appDisplayName;
>   }
> ```
> 
> **After (v2.0.3+)** - [`app.ts`
L175-L177](https://github.com/microsoft/teams.ts/blob/8638fbfd3e4e253d04b2e7514ef373ef66ed9546/packages/apps/src/app.ts#L175-L177):
>    ```typescript
> get name() {
>     return this._manifest.name?.full;
>   }
> ```
> The
[send()](https://github.com/microsoft/teams.ts/blob/33c95aee06f5583083c2e456d45666fa3e43242c/packages/apps/src/app.ts#L403-L405)
method checks if (!this.id || !this.name) and throws "app not started",
but this error message is misleading because:
> 
>   1. The app is started (app.start() completed successfully)
> 2. The actual issue is that manifest.name was not provided in the
constructor
> 
> This is a breaking change that affects any code I had using app.send()
for proactive messaging.
> 
> ### Steps to Reproduce
> 
> 1. Install @microsoft/teams.apps v2.0.3 or later
>   2. Create an App instance without the manifest.name option:
>   ```typescript
> const app = new App({
>     clientId: "...",
>     clientSecret: "...",
>     tenantId: "...",
>   });
> ```
>   3. Start the app and call app.send():
>   `await app.start(3978);`
> `await app.send(conversationId, "Hello"); // Throws "app not started"`
> 
> ### Expected Behavior
> 
> Either:
> - The error message should indicate the actual problem (e.g.,
"manifest.name is required for app.send()")
> - Or the SDK should fall back to this.tokens.bot?.appDisplayName for
backwards compatibility
> 
> 
> ### Actual Behavior
> 
> Throws Error: app not started which is misleading
> 
>   Workaround: Add manifest.name to the App constructor:
>   ```typescript
> const app = new App({
>     clientId: "...",
>     clientSecret: "...",
>     tenantId: "...",
>     manifest: {
>       name: { short: "MyApp", full: "My Application" },
>     },
>   });
> ```
> 
> ### SDK Version
> 
> 2.0.4
> 
> ### Node.js Version
> 
> 24.5.0
> 
> ### Additional Context
> 
> _No response_</issue_description>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> <comment_new><author>@heyitsaamir</author><body>
> Thanks! Yeah that is indeed a bug. We should not be looking at the
name when preparing to send. </body></comment_new>
> </comments>
> 


</details>

- Fixes #415

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for
you](https://github.com/microsoft/teams.ts/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: heyitsaamir <[email protected]>
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.

3 participants