User and Bot messages appear on same side of chat container - botframework

I built a QnA Maker and integrated it via Direct Line in my Website using BotFramework-WebChat for styling.
Messages of the user and the bot are appearing at the same side of the chat container. I can't figure why.
This is how it currently looks like:
This is the code I'm using:
<script>
const styleSet = window.WebChat.createStyleSet({
bubbleFromUserBackground: 'rgba(227, 227, 227, .1)',
hideUploadButton: true,
botAvatarInitials: 'WD',
sendTypingIndicator: true,
userAvatarInitials: 'you'
});
styleSet.textContent = Object.assign(
{},
styleSet.textContent,
{
fontFamily: '\'Lato\', sans-serif'
}
);
window.WebChat.renderWebChat(
{
directLine: window.WebChat.createDirectLine({
token: 'xxxxxx'
}),
styleSet,
userID: 'qna-homepage-bot',
username: 'Web Chat User',
locale: 'en-US',
},
document.getElementById('webchat')
);
document.querySelector('#webchat > *').focus();
</script>

I wasn't able to reproduce this, but I suspect you are setting your user ID to the same value as the bot ID. When Web Chat receives an activity, it sets the role property in the activity's from attribute based on the ID (you can take a look at the source code here). Web Chat then uses the role to determine how the activity is styled. If the bot id equals the user id, Web Chat will confuse the role attribute and apply the wrong CSS stylings. Try changing the userID value in the render Web Chat options to something else.
Note, the userID value should be unique for each user; otherwise, every conversation will share the same user state.
Hope this helps!

Related

Sending a JWT through Direct-line API to authenticate the user, in Microsoft chat bot

I need to send a JWt (access token) to the chatbot via directline. I'm using react as the front end, and the chatbot is integrated into the front end via botframework-webchat.
So far, I was able to send the access token through an activity, which is not recommended as I think.
Right now, the chatbot is asking the user to log in, which is not good because the user is already logged in to the application.
My first question - Is it possible to authenticate the chatbot by an id token instead of connecting with Azure AD, B2C, or any auth service provider?
If it is possible, How can I send the id token to the bot, via botframework-webchat
Thanks in advance
Here is my code for the front end
const Chatbot = (props) => {
const language = localStorage.getItem('language');
const directLine = useMemo(
() => createDirectLine({ token: <my_token>, locale: 'sv-se' }),
[]
);
useEffect(() => {
var activity = {
from: {
id: '001',
name: 'noviral',
},
name: 'startConversation',
type: 'event',
value: 'Hi noviral!',
locale: language === 'en' ? 'en-US' : 'sv-se',
};
directLine.postActivity(activity).subscribe(function (id) {
if (console) {
console.log('welcome message sent to health bot');
}
});
}, []);
return (
<Layout className="login-layout">
<div className="login-div">
<div className="chatbot">
<div className="consent-wrapper">
<ReactWebChat
directLine={directLine}
userID={'001'}
username="Noviral"
locale={language === 'en' ? 'en-US' : 'sv-se'}
></ReactWebChat>
</div>
</div>
</div>
</Layout>
);
};
export default withTranslation()(Chatbot);
Sending the token via an activity is acceptable as activities sent via Direct Line are secure. If you look over the 24.bot-authentication-msgraph sample, you can see that the default action the bot takes is to send an activity displaying the user's token.
As for authentication, the question doesn't seem to be what token you will use but rather how you will authenticate. If you don't use a service provider + login, how is the bot going to verify who the user is? That being said, there are some SSO (single sign-on) options available via Web Chat (see here) that, if a user is already logged in, then SSO could pick it up. You will have to look them over to decide if these options meet your needs.

Single sign on in Teams application between tabs and the bot

Using the Bot Framework w/ Microsoft.Bot.Builder v4.6.3
Is it possible to have users sign in only once using the web-based authentication flow, doesn't matter if they sign in via tabs or via bot conversation? If they sign in via a link from a tab, I'd like to have the bot know about this.
I have tried the following for test, omitting any security checks:
All pages are with the following js files imported:
https://statics.teams.microsoft.com/sdk/v1.4.2/js/MicrosoftTeams.min.js
https://cdnjs.cloudflare.com/ajax/libs/oidc-client/1.9.1/oidc-client.min.js
On load, the tab page executes microsoftTeams.initialize();
Add a button to the tab page:
<button onclick="authenticate()">Authenticate</button>
The authenticate function contains the following:
function authenticate() {
microsoftTeams.authentication.authenticate({
url: window.location.origin + "/tabs/tabAuthStart",
width: 600,
height: 535,
successCallback: function (result) {
// The debug function just displays what's sent to it using document.write()
debug(result);
},
failureCallback: function (reason) {
debug(reason);
}
});
}
The tabAuthStart page contains the following script which is executed on page load:
microsoftTeams.initialize();
const mgr = new Oidc.UserManager({
userStore: new Oidc.WebStorageStateStore(),
authority: '<my-identity-server>',
client_id: '<my-id-srv-client>',
redirect_uri: window.location.origin + '/tabs/tabAuthCallback',
response_type: 'id_token token',
scope: '<my-requested-scopes>',
accessTokenExpiringNotificationTime: 10,
automaticSilentRenew: true,
filterProtocolClaims: true,
loadUserInfo: true
});
mgr.signinRedirect();
After a successful sign in at the identity provider, I'm redirected back to /tabs/tabAuthCallback
On load, the /tabs/tabAuthCallback executes the following code:
microsoftTeams.initialize();
var mgr = new Oidc.UserManager({ userStore: new Oidc.WebStorageStateStore(), loadUserInfo: true, filterProtocolClaims: true });
mgr.signinRedirectCallback().then(function (user) {
// I expected something involving a bot to happen after calling this
microsoftTeams.authentication.notifySuccess({
idToken: user.id_token,
accessToken: user.access_token,
tokenType: user.token_type,
expiresIn: user.expires_at
})
}).catch(function (err) {
microsoftTeams.authentication.notifyFailure("UnexpectedFailure: " + err);
});
The pop-up window is closed and the successCallback function from the tab is executed successfully with the user information that I have sent. However, the bot is not in any way notified about this (as far as I know). I have set a breakpoint in the bot controller action resolved by POST /api/messages but it's never hit.
Do I need to handle this manually? I.e. pass the user info to the back-end? But even if so, how do I know which Teams user to associate this user info (i.e. access token) to?
If this is possible to do in a reliable and secure way, would it also be possible in the opposite direction, i.e. having the user token available to the tab if they have already been authenticated from a bot conversation or a messaging extension? Is there a reliable way to identify a Teams user who's navigating tabs, in order to obtain their access token from the back-end, assuming the back-end already obtained them via the authentication mechanism?

BotFramework - chatTitle option for V4

Migrating from BotFramework V3 to V4, not able to set the chatTitle of chat window.
This is my old code
BotChat.App({
user: { id: userID, name: 'test' },
botConnection: botConnection,
locale: 'fr-fr',
showUploadButton: false,
chatTitle: 'Assistant virtuel',
resize: 'detect'
})
Now with new version, 'chatTitle' is no longer working.
window.WebChat.renderWebChat(
{
directLine: webChatConnection,
userID: userID,
username: 'test',
locale: 'fr-fr',
chatTitle: 'Assistant virtuel',
},
document.getElementById('botDiv')
);
According to this issue Here
We omitted the chat title in Web Chat v4 (compare to v3) because:
It is one of the most popular customization
It can be easily done in HTML by appending HTML code just before Web Chat DOM element
It is more intuitive to do it in plain HTML than "customizing" in Web Chat, feel over-engineered if we do it that way
In this way, the user can customize the title as much as they want, for example, adding buttons to the chat title easily.
Check this Answer here if it has what you need using Javascript

How do I integrate Microsoft health bot to web application

I have created few scenarios in health bot designer. I am trying to integrate with my front end. However, I don't see any complete documentation around integrate process. I have already referred https://github.com/Microsoft/HealthBot-WebChat without any luck. How do I get directline link for healthbot. I have tried with web bot and able to generate directline but not sure how to link web bot channel to health bot scenario. Any help?
You can integrate the Healthcare bot service into a web application using WebChat. First, you need to get your WebChat Secret from the Healthcare Bot Service Manager. In the pane on the left, click on the integrations blade, select secrets in the drop down options, and copy the webchat_secret.
Once you have the secret, you can request a token from DirectLine and render a WebChat component on your web app. Take a look at the example below.
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Healthcare bot</title>
<script src="https://cdn.botframework.com/botframework-webchat/master/webchat.js"></script>
<style>
html, body { height: 100% }
body { margin: 0 }
#webchat,
#webchat > * {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="webchat" role="main"></div>
<script>
(async function() {
// Note, for the simplicity of this example, we are fetching the DirectLine token here;
// however, it is recommended that you create a backend REST API to generate and manage
// your tokens.
const res = await fetch('https://directline.botframework.com/v3/directline/tokens/generate',
{
method: 'POST',
headers: {
'Authorization': `Bearer <WEBCHAT_SECRET>`,
'Content-Type': 'application/json'
},
body: {
// The user id must start with `dl` and should be unique for each user.
User: { Id: 'dl_user_id' }
}
});
const { token } = await res.json();
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
}, document.getElementById('webchat'));
})().catch(err => console.log(err));
</script>
</body>
Note, for the simplicity of this example, we are fetching the DirectLine token here; however, it is recommended that you create a backend REST API to generate and manage your tokens.
Hope this helps!
Found a way to do it. We need to add a model and enable the trigger through Health Bot Management Portal
There is a direct way to trigger a scenario from the front end. If you want to completely rely on your own responses, then you have to turn off the built-in scenarios and call a scenario name in the event post javascript code. Look at the "trigger" element below:
botConnection
.postActivity({
type: "event",
value: {
trigger: "your_scenario_name_here", args: {}
},
from: your_user_name,
name: "BeginDebugScenario"
});

Bot Framework web chat + speech + specific voice

I'm trying to get web chat with my bot (V4 bot and web chat) to work with the speech cognitive service, using a specific voice. I've got it almost working as per this sample and others in the same folder (https://github.com/Microsoft/BotFramework-WebChat/blob/master/samples/06.c.cognitive-services-speech-services-js/index.html)
The only part of the equation I'm missing is whether I can specify the voice. I can't find how to specify voice in the samples and the web chat source code.
This page linked to from the speech cog service docco (https://learn.microsoft.com/en-gb/azure/cognitive-services/speech-service/speech-synthesis-markup) mentions specifying voice inside the SSML but I don't want to have to somehow crack open and modify the SSML being generated by the bot if I can avoid it.
Does anyone have any idea if this is possible, and if so how?
Thanks
Lee
OK I came to an answer on this myself after looking at the pony fill code. Partial snippet below. Update the list of voice to locale mappings to match the voice you want to use for the specified locale.
const speechServicesPonyfillFactory = await window.WebChat.createCognitiveServicesSpeechServicesPonyfillFactory({ authorizationToken, region });
return options => {
const ponyfill = speechServicesPonyfillFactory(options);
var speechSynthesisUtterance = ponyfill.SpeechSynthesisUtterance;
var speechSynthesis = ponyfill.speechSynthesis;
speechSynthesis.getVoices = function () {
return [
{ lang: 'en-US', gender: 'Male', voiceURI: 'Microsoft Server Speech Text to Speech Voice (en-US, BenjaminRUS)' }
];
}
return {
SpeechGrammarList: ponyfill.SpeechGrammarList,
SpeechRecognition: ponyfill.SpeechRecognition,
speechSynthesis: speechSynthesis,
SpeechSynthesisUtterance: speechSynthesisUtterance
}
};
};
...
var ponyfillFactory = await createSpeechPonyfillFactory({ authorizationToken, region });
...
// Do the usual stuff from the sample to get auth token and region...
window.WebChat.renderWebChat({
directLine: directLine,
webSpeechPonyfillFactory: ponyfillFactory,
store
}, document.getElementById('webchat'));

Resources