javascriptproxybotframework

ClientAuthError: network_error: Network request failed - ConfigurationBotFrameworkAuthentication


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 ?


Solution

  • 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;
              }
            },
          },
        },
      })
    );