Search code examples
botframework

Proactive Messaging: 'Authorization has been denied for this request' on server restart


We are using the botframework to power a chatbot experience in Microsoft Teams. Many of our use cases involve proactively messaging users, we have followed the documentation closely by storing/retrieving conversation references and trusting the serviceUrl from the retrieved reference, allowing us to successfully send proactive messages.

We have noticed that whenever we restart the bot, we get the following error when attempting to send a proactive message: Authorization has been denied for this request.

We first encountered this error message after the bot had not been interacted with for at least a day which was resolved by altering the following statement with an increased expiration time on the serviceUrl: MicrosoftAppCredentials.trustServiceUrl(conversationReference.serviceUrl, new Date(8640000000000000));

However, we now get this message every time the bot server is restarted, which happens often due to our CI/CD pipelines.

We can resolve this issue quite quickly by manually messaging the bot beforehand, which will then work, however this is quite cumbersome as we can have many deployments per day.

Steps to Reproduce

  • Restart bot server
  • Send a proactive message to the bot (we use a queue for this)
  • Message will not send with the 'Authorization has been denied for this request.' error being thrown

To Manually Resolve

  • Send a message the bot and wait for reply
  • Attempt to send proactive message again
  • Message will successfully be sent

Additional context

Envrionment: Node.js Docker container deployed to AWS


Solution

  • Managed to figure this out by using the botframework-connector to create the conversation and send the proactive message.

    Assuming you have stored and retrieved a conversationReference, start by connecting to the bot

    const msAppCredentials = new MicrosoftAppCredentials(MS_APP_ID, MS_APP_PASSWORD);
    const client = new ConnectorClient(MSAppCredentials, { baseUri: conversationReference.serviceUrl });
    

    Once connected, you can build up the conversation parameters and create the conversation:

    const parameters = {
      bot: { id: MS_APP_ID, name: conversationReference.bot.name }, 
      members: [{ id: conversationReference.user.id, name: conversationReference.user.name }],
      activity: MessageFactory.text("oi oi oi"),
      tenantId: conversationReference.conversation.tenantId,
      isGroup: false,
      channelData: { ...conversationReference.conversation.channelData }
    }
    
    const resource = await client.conversations.createConversation(parameters);
    

    Finally, send the message to the conversation

    await client.conversations.sendToConversation(resource.id, parameters.activity);