I am creating a chatbot using Azure Bot resources with a node JS application.
I use the botbuilder
package to create an adapter.
credentialsFactory = new MsalServiceClientCredentialsFactory(
'APP_ID',
new ConfidentialClientApplication({
auth: {
clientId: 'APP_ID',
clientSecret: 'APP_PASSWORD',
authority: 'https://login.microsoftonline.com/botframework.com',
},
}),
);
const httpsProxyAgent = getHttpsProxyAgent();
const botFrameworkAuthentication = new ConfigurationBotFrameworkAuthentication(
undefined,
credentialsFactory,
undefined,
undefined,
{
proxySettings: httpsProxyAgent
? {
host: httpsProxyAgent.proxy.hostname,
port: +httpsProxyAgent.proxy.port,
}
: undefined,
},
);
const adapter = new CloudAdapter(botFrameworkAuthentication);
await adapter.process(req, res, async (context) => {
// Do something
await context.sendActivity(await response.component.GetMessage({
userSession,
userMessage,
template,
responseMessageOverride: null,
}));
});
At first, we got ENOTFOUND login.botframework.com
when receiving a request from Bot framework because of our corporate proxy. We fixed this by adding proxySettings
as shown above.
We used the following sample to configure the proxy : https://github.com/microsoft/BotBuilder-Samples/blob/main/samples/javascript_nodejs/49.echo-proxy-bot/index.js
Now, we get the following error:
err: {
"type": "ClientAuthError",
"message": "network_error: Network request failed",
"stack":
ClientAuthError: network_error: Network request failed
at createClientAuthError (file:///opt/app-root/src/node_modules/.pnpm/@azure+msal-common@14.16.0/node_modules/@azure/msal-common/dist/error/ClientAuthError.mjs:255:12)
at ClientCredentialClient.sendPostRequest (file:///opt/app-root/src/node_modules/.pnpm/@azure+msal-common@14.16.0/node_modules/@azure/msal-common/dist/client/BaseClient.mjs:131:23)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async ClientCredentialClient.executePostToTokenEndpoint (file:///opt/app-root/src/node_modules/.pnpm/@azure+msal-common@14.16.0/node_modules/@azure/msal-common/dist/client/BaseClient.mjs:82:26)
at async ClientCredentialClient.executeTokenRequest (file:///opt/app-root/src/node_modules/.pnpm/@azure+msal-node@2.16.2/node_modules/@azure/msal-node/dist/client/ClientCredentialClient.mjs:155:30)
at async ConfidentialClientApplication.acquireTokenByClientCredential (file:///opt/app-root/src/node_modules/.pnpm/@azure+msal-node@2.16.2/node_modules/@azure/msal-node/dist/client/ConfidentialClientApplication.mjs:112:20)
"errorCode": "network_error",
"errorMessage": "Network request failed",
"subError": "",
"name": "ClientAuthError",
"correlationId": "REDACTED"
}
I tried the run my app on my personal computer and it works. I suppose there is a missing proxy config somewhere, but I cannot figure out. Is there another configuration necessary for botframework to use the proxy settings when connecting to Azure ?
I figured out how to fix this error by overriding the networkClient as seen in this issue: https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/6527#issuecomment-1746091561
credentialsFactory = new MsalServiceClientCredentialsFactory(
'APP_ID',
new ConfidentialClientApplication({
auth: {
clientId: 'APP_ID',
clientSecret: 'APP_PASSWORD',
authority: "https://login.microsoftonline.com/botframework.com",
},
system: {
// Workaround use native fetch with our proxy settings
// Original HTTP client used by msal-node: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/src/network/HttpClient.ts
// Github issue related: https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/6527#issuecomment-1746091561
networkClient: {
sendGetRequestAsync: async (
url: string,
options?: NetworkRequestOptions
) => {
try {
const response = await fetch(url, {
...options,
method: "GET",
});
return {
status: response.status,
headers: Object.fromEntries(response.headers.entries()),
body: await response.json(),
};
} catch (error) {
Logger.error(
{ error },
"[SERVICE] BotFrameworkService networkClient.sendGetRequestAsync"
);
throw error;
}
},
sendPostRequestAsync: async (
url: string,
options?: NetworkRequestOptions
) => {
try {
const response = await fetch(url, {
...options,
method: "POST",
});
return {
status: response.status,
headers: Object.fromEntries(response.headers.entries()),
body: await response.json(),
};
} catch (error) {
Logger.error(
{ error },
"[SERVICE] BotFrameworkService networkClient.sendPostRequestAsync"
);
throw error;
}
},
},
},
})
);