I have to design a bot that can answer what my app users are asking about their project. Answers will be the implementations of certain APIs. These APIs that my bot will be using to give answers are secured by user-specific authentication tokens. As of now, I have written a bot using Microsoft bot framework and LUIS that understands certain utterances and can give answers with calling project APIS.I am confused about how to do these things :
How to pass user authentication token to bot? This toke is generated using user credentials (usename+password). Inside my bot code, I can't use username/password for generating the token.I need to pass them from client app only.
How to pass project Id to the bot about which user is asking the question? The user might be calling the name of the project, or will select the project from a list. The bot should be intelligent enough to change answers based on project Id.
As of now, I am handing second part using LUIS utterances + Entity combination. So my question(utterance is ): "tell me what's new in {projectid}" where projectid is my project entity.
But for the first question, I am still looking for the solution. Please suggest.
You will need few modification in your bot to use DirectLine API instead of webchat. Directline API gives you flexibility to send your own data to Bot. There are few reserved properties inside Activity.From from which you can read your data.
var userProperties = [];
userProperties.push({
projectId:
{Project_Id_Will_Be_Sent_Using_This},
UserToken:
{User_Generated_Token}
});
BotChat.App({
directLine: { secret: 'BOT-SECRET-KEY' },
user: { id: '', name:'', properties:userProperties },
bot: { id: 'YOUR-BOT-ID' },
resize: 'detect',
}, document.getElementById("bot"));
Please revert if you need any help around this.
Related
I am trying to implement the functionality of the password as shown in this link.
https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/05.custom-components/f.password-input
but how to pass the password activity form the bot to the front end. I am using the c# template for the developing the bot.
As per my understanding, we need to pass a password activity from the bot to the front-end for the execution of the password things as mentioned in the link.
An example would be help-full in knowing how to pass this type of customer activity forms the bot.
Thanks,
I used this sample myself for one of my bots. The bot logic is built in node but I guess it shouldn't be hard to translate to c#
const askPwd =
{
name: 'passwordInput',
type: 'event'
};
await stepContext.context.sendActivity(askPwd);
return await stepContext.prompt(PASSWORD_PROMPT, '');
In c# this will probabaly translate into something like this (I don't know c#):
Activity activity = new Activity
{
Type = ActivityTypes.Event,
Name = "passwordInput"
};
await stepContext.Context.SendActivityAsync(activity, cancellationToken);});
I have created a proactive bot that basically asks certain questions to a user when a user starts conversation with the bot. The bot is deployed in Microsoft Teams environment. Is there any way that i can send automated message to a bot in a channel? I know messages can be sent using powershell by utilizing webhook url exposed by a particular team or using MS Flow. But I want to mention bot (e.g. #mybothandle) in the message so the bot starts asking questions by itself than requiring the user to start the conversation (by mentioning the bot manually) but not finding the way to mention.
Your suggestions are welcome.
Basically you want to message the user directly at a specific point in time (like 24 hours later). I'm doing this in a few different bots, so it's definitely possible. The link that Wajeed has sent in the comment to your question is exactly what you need - when the user interacts with your bot, you need to save important information like the conversation id, conversation type, service url, and To and From info. You can store this, for instance, in a database, and then you can actually have a totally separate application make the call AS IF IT WAS your bot. In my bots, for example, I have the bot hosted in a normal host (e.g. Azure Website) but then have an Azure Function that sends the messages, for example, 24 hours later. It just appears to the user as if it was a message from the bot, like normal.
You will also need the Microsoft App ID and App Password for your bot, which you should have already (if not, it's in the Azure portal).
In your "sending" application, you're going to need to create an instance of Microsoft. Bot.Connector.ConnectorClient, like follows:
var Connector = new ConnectorClient(serviceUrl, microsoftAppId: credentialProvider.AppId, microsoftAppPassword: credentialProvider.Password);
You also need to "trust" the service url you're calling, like this:
MicrosoftAppCredentials.TrustServiceUrl(serviceURL);
Then you create an instance of Microsoft.Bot.Schema.Activity, set the required properties, and send it via the connector you created:
var activity = Activity.CreateMessageActivity();
activity.From = new ChannelAccount([FromId], [FromName];
activity.Recipient = new ChannelAccount([ToId], [ToName]);
activity.Conversation = new ConversationAccount(false, [ConversationType], [ConversationId]);
activity.Conversation.Id = [ConversationId];
activity.Text = "whatever you want to send from the bot...";
Connector.Conversations.SendToConversationAsync((activity as Activity)).Wait();
All the items in square braces are what you get from the initial conversation the user is having with the bot, except that the From and To are switched around (when the user sends your bot a message, the user is the FROM and your Bot is the TO, and when the bot is sending you switch them around.
Hope that helps
To all Future Visitors, Microsoft Graph API (Beta) now provides a way to send message and mention the bot/user using following endpoint:
https://graph.microsoft.com/beta/teams/{group-id-for-teams}/channels/{channel-id}/messages
Method: POST
Body:
"body": {
"contentType": "html",
"content": "Hello World <at id=\"0\">standupbot</at>"
},
"mentions": [
{
"id": 0,
"mentionText": "StandupBot",
"mentioned": {
"application": {
"id": "[my-bot-id]",
"displayName": "StandupBot",
"applicationIdentityType": "bot"
}
}
}
]
}
However, there is a bug that bot doesn't respond when receives the message:
Bot is not responding to #Mention when sending message using Graph API
We have a scenario where a user would first login to web application before starting a conversation with Azure Bot.
My question is how do we ensure bot will only allow user to ask financial questions related to his own accounts considering the bot is capable of answer questions related to financial holding of the person logged in.
Basically is there a way to pass principal object to the bot before the conversation starts. If yes how do we pass those details.
The BotFramework currently does not support single sign-on; however, the BotFramework Web Chat Development team has recommended different approaches to create a single sign-on experience and is currently working on developing a sample.
The main approach recommends piggybacking the authentication token on every outgoing message by adding it to the activity's channel data. To do this, you can create a custom middleware that appends the additional data. Take a look at the code snippet below.
const store = window.WebChat.createStore(
{},
({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/POST_ACTIVITY') {
// The channelData submitted here is very similar to HTTP cookies and vulnerable to forgery attack.
// Make sure you use signature to protect it and verify the signature on the bot side.
// To minimize unexpected behaviors, we recommend to treat the "action" object as if it is immutable.
// We use simple-update-in package to update "action" with partial deep cloning.
action = window.simpleUpdateIn(action, ['payload', 'activity', 'channelData', 'token'], () => token);
}
return next(action);
}
);
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
// We will use a custom version of Redux store, which we added middleware to handle backchannel messages.
store
}, document.getElementById('webchat'));
On the bot side, you can retrieve the token from the channel data and use it to make various requests. For more details on adding data to outgoing activities, take a look at this sample.
For more details regarding recommended approaches, take a look at this issue on GitHub. The Web Chat Development team is also using it to track the progress of the sample.
Hope this helps.
I am trying to build a bot and use it within a chat app. I think Microsoft Bot Builder is the one for me.
I looked into its documentations and tried them in the emulator.
I noticed that in these examples, you send texts to the bot either using
"consoleconnector" or "chatconnector", as the example shows.
server.post('/api/messages', connector.listen());
// Receive messages from the user and respond by echoing each message
back (prefixed with 'You said:')
var bot = new builder.UniversalBot(connector, function (session) {
session.send("You said: %s", session.message.text);
});
I don't want a new endpoint. I want to call the bot like calling a function: give the incoming message from a user and the function returns bot's response.
Is it possible? If yes, please tell me how to do it.
If it is not possible, then only way is to call it as a rest API as shown above.
In this case, do i still need "MICROSOFT_APP_ID" and "MICROSOFT_APP_PASSWORD"?
Note that, I don't want to deploy the bot to azure or aws now. I want to use it local.
Could anyone help me explain these? Thanks in advance!
The Bot Framework is built to function as an API - it takes a request and sends a response. The framework doesn't provide a callback or promise to capture the response so this approach simply wouldn't work. Take a look at the DirectLine API if you want to embed the framework within another application.
You need to use the MS App id and password for all channels apart from the Emulator. If you use DirectLine API, you will also have to pass a secret token.
How to secure the traffic from Microsoft Teams to a bot, so that bot could be answering on company specific questions / discussions and would not need to be exposed as anonymous WebAPI?
Bot integration to Teams UIs is easy from bot framework side, but right now there's no documentation for how to isolate bot only for specific enterprise.
Business case - We want to build enterprise specific bot, which could answer questions only specific to that particular enterprise where the questions are coming from. Technically this could be done with app-only access to SharePoint or Microsoft Graph, but we cannot expose this kind of WebAPI anonymously for Internet.
Any design patterns for this?
This is now possible, and I've actually even implemented it for Hubot in CoffeeScript and Node.JS. What I've described below is what it would look like in JavaScript/Node.JS.
Define an environment variable that, when set, filters for a particular tenant ID, OFFICE_365_TENANT_FILTER. (Doing it this way is a handy way of turning this feature on in production but not necessarily during development.)
For Microsoft Teams, the Office 365 tenant ID can be found here: session.message.sourceEvent.tenant.id.
The most elegant way to do it is to check for the tenant ID as middleware, and just drop further processing of the message if the filter is set and it doesn't match:
// [...]
var connector = new builder.ChatConnector({
appId: process.env.MICROSOFT_APP_ID,
appPassword: process.env.MICROSOFT_APP_PASSWORD
});
var bot = new builder.UniversalBot(connector);
// Middleware to check for OFFICE_365_TENANT_FILTER and only continue processing if it matches.
// If OFFICE_365_TENANT_FILTER is not specified, do nothing.
bot.use({
botbuilder: function(session, next) {
var targetTenant = typeof(process.env.OFFICE_365_TENANT_FILTER) !== "undefined" ? process.env.OFFICE_365_TENANT_FILTER : null;
var currentMsgTenant = typeof(session.message.sourceEvent.tenant) !== "undefined" ? session.message.sourceEvent.tenant.id : null;
if (targetTenant !== null) {
if (targetTenant == currentMsgTenant) {
next();
}
else {
console.log("MS Teams: Attempted access from a different Office 365 tenant (" + currentMsgTenant + "): message rejected");
}
}
else {
next();
}
}
});
// [...]
Here's how to do this in C#, the SDK exposes the TenantFilter that allows you to add this action filter to the controller class as shown below.
using Microsoft.Bot.Connector.Teams;
namespace Microsoft.Teams.Samples.HelloWorld.Web.Controllers
{
[BotAuthentication, TenantFilter]
public class MessagesController : ApiController
{
[HttpPost]
public async Task<HttpResponseMessage> Post([FromBody] Activity activity)
The tenant filter will take a comma separated list of tenantIds that will need to be placed in the web.config
<configuration>
<appSettings>
<!--other settings-->
<add key="AllowedTenants" value="*TenantId1,TenantId2,...*"/>
Find your Office 365 tenant ID shows how you can do it through PowerShell.
It is not currently possible to know the tenant-id of the user chatting with the bot right away, unless the bot authenticates the user first. Please take a look at AuthBot. It illustrates how to send a sign-in link to a user and authenticate the user against AAD.
Although not exactly what you are looking for, you can create custom bots which will be scoped to individual Teams.
The security key/HMAC auth will prevent others from accessing the API. With the drawback that you will have to configure the bot with a separate security token for every Team where you want to use it.