Skip to content

Teams SDK v2 Question: How to use user-assigned identity with Bot Framework CloudAdapter (401 Unauthorized issue) #348

@GordonHo-IPG

Description

@GordonHo-IPG

Hi experts,

I built a chatbot using the M365 Agent Toolkit and the Teams template. It works quite well. I noticed that Teams SDK v2 supports the message streaming function, which brings a huge improvement in user experience.

However, I’m still unable to get the bot service to work with a new web app — it always throws a 401 Unauthorized error when the web application is trying to send the message to the bot services. Since I’m using a user-assigned identity for authentication, I made some adjustments to the adapter, but it still doesn’t work.

Could you let me know if there are any libraries that work out of the box, similar to TeamsAdapter?

import {
    CloudAdapter,
    ConfigurationBotFrameworkAuthentication,
    TurnContext
} from 'botbuilder';
import { DefaultAzureCredential } from '@azure/identity';

console.log(`MicrosoftAppId: ${process.env.MicrosoftAppId}`);
console.log(`AZURE_CLIENT_ID: ${process.env.AZURE_CLIENT_ID}`);
console.log(`AZURE_TENANT_ID: ${process.env.AZURE_TENANT_ID}`);

const credentialsFactory = {
    createCredentials: async (_appId: string, _audience: string, _loginEndpoint: string, _validateAuthority: boolean) => {
        const credential = new DefaultAzureCredential();
        const token = await credential.getToken("https://api.botframework.com/.default");
        return {
            appId: process.env.MicrosoftAppId!,
            token: token.token,
            getAuthorizationHeader: () => `Bearer ${token.token}`,
            signRequest: async (webResource: any) => {
                if (!webResource.headers) {
                    webResource.headers = {};
                }
                webResource.headers["Authorization"] = `Bearer ${token.token}`;
                return webResource;
            }
        };
    },
    isValidAppId: async (_appId: string) => true,
    isAuthenticationDisabled: async () => false,
};

const botFrameworkAuthentication = new ConfigurationBotFrameworkAuthentication(
    {},
    credentialsFactory
);

const adapter = new CloudAdapter(botFrameworkAuthentication);

adapter.onTurnError = async (context: TurnContext, error: Error) => {
    console.error(`\n [onTurnError] unhandled error: ${error}`);
    await context.sendTraceActivity(
        'OnTurnError Trace',
        `${error}`,
        'https://www.botframework.com/schemas/error',
        'TurnError'
    );
    await context.sendActivity('The bot encountered an error or bug.');
    await context.sendActivity('To continue running this bot, please fix the bot source code.');
};

export default adapter;

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions