I am using directline with webchat.
window.WebChat.renderWebChat(
{
directLine: window.WebChat.createDirectLine({
secret: '<my secret key>',
}),
//customizing web chat styles.
styleOptions: styleOptions
},
document.getElementById('webchat')
);
This my javascript that initiates the webchat with the secret key. Is there anyway that I can receive the conversationId back in the javascript after initializing the webchat as above?
This is easily achieved by utilizing the method demonstrated in the 04.api/a.welcome-event sample. Upon Web Chat connecting, an event is sent to the bot indicating this. When the event is received by the bot the bot sends a return activity. The return activity, by design, includes the conversationID.
In short, here is the code you can reference. Taken from the sample, this sends the users location based on the browser's properties.
From Web Chat:
https://github.com/microsoft/BotFramework-WebChat/tree/master/samples/04.api/a.welcome-event
From the bot:
if (context.activity.name === 'webchat/join') {
await context.sendActivity(
`Got \`webchat/join\` event, your language is \`${(context.activity.value || {}).language}\``
);
}
Related
Hi I would like to update profile information of slack account using API.
I used WebClient using user token, setting profile:write scope.
I set Slack Bot subscribing slack events, but it only updated my profile. Whoever tried to update his/her profile, my(slack bot authorizer) profile updated. There is already user params in set method.
await client.users.profile.set({
user,
profile: {
status_emoji,
status_text,
} as any,
})
I have a SPA, and I am trying to send a message on behalf of a user in Teams via -
POST https://graph.microsoft.com/v1.0/teams/{teamid}/channel/{channelid}/messages
through the same.
But I am continuously getting this error -
{
"error": {
"code": "Unauthorized",
"message": "Unauthorized",
"innerError": {
"date": "2020-12-03T06:09:02",
"request-id": "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"client-request-id": "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
}
}
}
The SPA is build using Azure AD App registrations and the Following API permissions have been given to the app :
ChannelMessage.Send (Delegate) , Chat.ReadWrite (Delegate), ChatMessage.Send (Delegate).
The above API works when calling from the Microsoft Graph explorer portal.
I also compared the access token on jwt.io from both Graph Explorer and My Azure AD application and both have the scopes -
[ ChannelMessage.Send ] which is required to send a message to a channel
Need help on this if I have missed something out or if I am doing something wrong.
Posting a message to channel using Send Channel Message Graph API requires ChannelMessage.Send Group.ReadWrite.All permissions
Here is the code snippet for sending messages to channel, you need to implement authProvider to pass it graphClient, I tested it for my tenant and I was succesfully able to send message in Channel.
Below is Code snippet
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var chatMessage = new ChatMessage
{
Body = new ItemBody
{
Content = "Hello World"
}
};
await graphClient.Teams["{TeamId}"].Channels["{ChannelId}"].Messages
.Request()
.AddAsync(chatMessage);
I'm not an expert on this, but I think you can't connect directly from an untrusted client (i.e. a SPA) to the Graph directly, and that you'd first need to get an "on behalf of" token (which means you'd need to have your own backend API to make a secure connection and retrieve this token). You can see a sample for this (dotnet and node) over here: https://github.com/HiltonGiesenow/teams-dev-samples/tree/add-tabs-sso-sample
I need to make a bot to send a message each ten minutes using Javascript. I'm using Microsoft Bot Framework, this is the entry code:
const restify = require('restify');
const botbuilder = require('botbuilder');
var adapter = new botbuilder.BotFrameworkAdapter({
appId: process.env.MicrosoftAppId,
appPassword: process.env.MicrosoftAppPassword
});
let server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
console.log(`\n${server.name} listening to ${server.url}`);
console.log(`\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator`);
});
server.post('/api/messages', (req, res) => {
adapter.processActivity(req, res, async (turnContext) => {
if (turnContext.activity.type === 'message') {
const text = turnContext.activity.text;
await turnContext.sendActivity(`You just said: ${ text }`);
}
});
});
Basically that responds with "You just said: x" to whatever the person talking to the bot said.
What I need is the bot to be in group in Skype and send a message each ten minutes.
However, in my example, the server awaits for a POST to /api/messages, then it uses the adapter to process that request and fires the "sendActivity" method from the turnContext, which comes from the processActivity method.
How can I just send a message at a fixed interval, and ignore all messages/mentions.
What you want to do is called proactive messaging. You can have a look at this document and the sample it references to better understand how to do this.
If you want your proactive messages to be triggered by a timer then you can run the timer on a thread in your bot, though it's generally recommended to have the timer running externally.
To disable messaging for your bot, simply choose that option in your channel configuration. I'm not sure how you'll retrieve the conversation ID if you disable messaging, though.
If you still want your bot to receive messages but just don't want to reply to them, simply edit the part of your bot code that responds to the condition turnContext.activity.type === 'message'.
Please keep in mind that Skype bot features may become increasingly limited. You should see an official message in your Skype channel configuration that says:
As of October 31, 2019 the Skype channel will no longer be accepting new Bot registrations. Current Skype bots will continue to run uninterrupted.
when receiving a message from pubnub, there is no information on the sender. how to know if it's a message from visitorA or visitorB ? there are examples on the web where the sender sends his name with the message, but how to know he isn't spoofing someone else's identity ?
here is an example of a chat interface :
<html>
<body>
<form id="message_form">
<input id="message_input" type="text"/>
</form>
<div id="chat"></div>
<script src="http://cdn.pubnub.com/pubnub-3.7.1.min.js"></script>
<script>
var pubnub = PUBNUB.init({
publish_key: 'demo',
subscribe_key: 'demo'
});
pubnub.subscribe({
channel: 'chat',
message: function(message){
var div = document.createElement("div");
div.textContent = message;
var chat = document.getElementById("chat");
chat.appendChild(div);
}
});
var form = document.getElementById("message_form");
form.onsubmit = function(e) {
var input = document.getElementById("message_input");
pubnub.publish({
channel: 'chat',
message: input.value
});
input.value = '';
e.preventDefault();
};
</script>
</body>
</html>
Chat User Identification
You can identify the sender by creating a Unique ID as well as a Name attached to the message payload of the chat conversation. This is similar to IRC strategies but a bit more simplistic.
var user_id = PUBNUB.uuid();
var user_name = name.value;
var user_message = input.vaule;
Here is a full example which includes the HTML elements for UserName input. Notice also that I added a safe_text() method to prevent XSS attacks.
<form id="message_form">
Name: <input id="name_input" value="John" type="text"/><br>
Message: <input id="message_input" value="Hi" type="text"/><br>
<input type="submit" value="send">
</form>
<div id="chat"></div>
<script src="http://cdn.pubnub.com/pubnub-dev.js"></script>
<script>
var userid = PUBNUB.uuid();
var pubnub = PUBNUB({
publish_key : 'demo',
subscribe_key : 'demo',
uuid : userid
});
function safe_text(text) {
return (''+text).replace( /[<>]/g, '' );
}
pubnub.subscribe({
channel: 'chat',
message: function(message){
var div = document.createElement("div");
div.textContent =
safe_text(message.name) + ": " +
safe_text(message.text);
var chat = document.getElementById("chat");
chat.appendChild(div);
}
});
var form = document.getElementById("message_form");
form.onsubmit = function(e) {
var input = document.getElementById("message_input");
var name = document.getElementById("name_input");
pubnub.publish({
channel: 'chat',
message: { name : name.value, text : input.value, userid :userid }
});
input.value = '';
e.preventDefault();
};
</script>
While this demonstration provides you with a quick and easy getting started app, you will want to add more enhanced chat security and chat authentication systems.
For additional resources for building chat applications check out Build Real-time Chat Apps in 10 Lines of Code guide and also Building A Basic Chat Application.
Chat Access Control Layer ACL
You will need to add Security ACL Access Control Layer. With PubNub Access Manager (PAM) you can control who has access by granting users permission with access tokens.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Grant Chat Access to Secured Conversations
// All server-side data is stored according to defined security policies.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
var pubnub = PUBNUB({
publish_key: "PUBLISH_KEY",
subscribe_key: "SUBSCRIBE_KEY",
secret_key: "SECRET_KEY"
})
pubnub.grant({
channel : "CHANNEL",
callback : receiver,
error : receiver,
ttl : 60, // Minutes
read : true,
write : true,
auth_key : "AUTH_KEY"
});
It is recommended to run this level of ACL code on Trusted Systems such as your own data center servers.
Sending/Receiving Secure Encrypted Messages
PubNub client libraries offer built-in Advanced Encryption Standard (AES) 256-bit encryption. To use message encryption, simply use cipher_key at initialization.
To enable Transport Layer Encryption with TLS and the ssl flag.
Then publish/subscribe as usual.
var pubnub = PUBNUB({
subscribe_key: 'sub-c-f762fb78-...',
publish_key: 'pub-c-156a6d5f-...',
ssl: true,
cipher_key: 'my_cipherkey'
});
Message Verification for Identity of Sender
Attaching user's information to each message is efficient and provides a very powerful level of flexibility within your application. However malicious users may attempt to spoof the identity of users and therefor impersonate other users. In the sample app we have shown that it is easy to impersonate anyone by changing your name in the "message_form" field. This is the same situation you encounter with email and SMTP where arbitrary email header impersonations are possible unless you provide a way to verify the identity of the sender. There is a solution! 😄
Digital Signatures are fingerprints with embedded secure cryptographic hashes of key components of the message payload optionally including a salt (sometimes a timestamp) and then signing/encrypting with an asymmetric secret key which is used to verify the identity of the sender. This process is used to block spoofers and impersonations.
A digital signature is a mathematical scheme for demonstrating the authenticity of a digital message or document.
Message Verification for Chat Applications
Start by assuming that only the chat users have been granted access and they can publish and subscribe to chat channels using grant and revoke techniques available in your PubNub Access Manager implementation.
The challenge here is that in a group chat room, your chat users have been granted auth_tokens yet they still can impersonate other chat users on the channel.
The goal here is to verify two things when a client receives a message.
Identity of sender.
Integrity of message.
Using asymmetric cryptography, you can provide a layer of validation and security to your users' messages by creating a digital signature. A valid digital signature gives a recipient reason to believe that the message was created by a known sender, that the sender cannot deny having sent the message (authentication and non-repudiation), and that the message was not altered in transit (integrity). Digital signatures are commonly used for financial transactions and message oriented communication such as email and chat and in other cases where it is important to detect forgery or tampering.
You will start by issuing each of your chat users' a set of keys, server generated, with a public-key (asymmetric) algorithm such as ECC/RSA via your server after user login. I recommend ECC as the key size is much smaller than RSA with comparable cryptographic strength. Each chat user in a chatroom is notified of other chat users' public key via a secured read only side-channel. Your users must only receive the Public Key from a public READ-ONLY channel controlled by your server's trusted and secure environment. Your server will be able to write each user's Public Key to this READ-ONLY channel. Your users will read from this channel.
Your user's can receive each other's Public Keys via a PubNub History call before joining the chat room. They should also open a subscription to the same channel to get public key of new chat users joining the chatroom.
The users' Private Key must not be exposed to anyone but the verified owner. This can be done upon email/password sign-on and you can send the private key to the verified user as soon as they log-in.
Sending a Chat Message with Attached Digital Signature
{ userId: 123456,
profilePic: "http://www.chats.com/user1234.jpg",
message: "Hello World",
signature: "tnnArxj06cWHq44gCs1OSKk/jLY" }
You will create the signature by concatenation of the following base string (userId+profilePic+message). Next you need to calculate a message digest using SHA1(signature_base_string) or SHA256(signature_base_string). Now you can use this cryptographically generated hash to sign with the users' private key using an ECC/RSA asymmetric algorithm.
Now attach this digital signature to chat message as shown in the example above and on to the final phase of Chatroom Message Verification.
Chatroom Message Verification
While subscribed to the chatroom channel you will receive user sent chat message with an attached digital signature. You will use this signature to verify the chat message's authenticity. If the message was an attempted spoof you will drop the message altogether.
// Digitally Signed Chat Message
{ userId: 123456,
profilePic: "http://www.chats.com/user1234.jpg",
message: "Hello World",
signature: "tnnArxj06cWHq44gCs1OSKk/jLY" }
To verify the signature you will create the signature by concatenation of the following base string (userId+profilePic+message). Next you need to calculate a message digest using SHA1(signature_base_string) or SHA256(signature_base_string). Now using the chat users' public key you already have for userId 123456 you can Verify/Decrypt digital signature to get original message digest you just generated which was also created by the sender.
Compare current message digest and original message digest. If they are the same then the message is authentic and you have successfully verified the sender's message using Message Verification via digital signing. If the digests do not match, it's a phony message and you may disregard the impersonator.
Creating a PKI Public Key Infrastructure using PubNub
You'll need a way to securely transmit public keys via a read-only PKI. PubNub provides to you a way for exposing a secure read-only PKI list for your chat users. Important to note that PKI requires asymmetric key algorithm like ECC or RSA. Also we are using these crypto algorithms for creating digital signatures rather than encrypting the data. This means we will be able to identify and verify the sender by successfully decrypting the signature using the public key and verifying the salted signed string matches.
Public Key is used as the Decryption Key and Verify Key.
Private Key is used as the Encryption Key and Signing Key.
It is important to note that you should only print the username retrieved from the Public Key Trusted Source and not from the message content. The message content is only used for signing and verifying Identity. If an Identity is changed it must be relayed via the PKI using PubNub’s Broadcast mechanism and Storage and Playback for Secure Authorization.
Access tokens, Identity Name/Photo and Asymmetric Keys must only be generated from trusted execution environments on your servers and relayed over PubNub's Authorized Read-only PKI data channels.
In the most recent PubNub SDKs (v4), the publisher UUID is now included in subscribe response.
{
actualChannel: null,
channel: "my_channel_1",
message: "Hello World!",
publisher: "pn-58e1a647-3e8a-4c7f-bfa4-e007ea4b2073",
subscribedChannel: "my_channel_1",
subscription: null,
timetoken: "14966804541029440"
}
I'm a bit confused on the presence-channels in Pusher's platform, as I'm building a chat application from scratch. Now, I know some of you guys have seen tons of "realtime chat app" topics around, but, I'm looking for a peer-to-peer chat and not the site-wide global thingy. More like a facebook chat, where you can go one-to-one.
Now, I've seen an example in PubNub's demos (named Babel) but, that thing is far from what I'm looking for because I've checked the requests in the console and even if it's not shown, the sent messages between other users are shown in my network request logs too because it's being filtered in JS and not server-side and thats not something I want for sure.
So, coming back to the subject,
I'm aware of the channel / private-channel / presence channel functionality, and I decided to do this:
When opening the app, every user subcribes to his private-user_id channel ( creates, if it doesn't exist already ).
At the same time ( while opening the app ) user1 subscribes to a presence-global channel where others keep track if friends are online.
When others want to send him a message, e.g. user2 to user1, he subscribes to private-1 thereafter javascript will process the events.
Now, I know something's wrong with this because.. if user3 would send a message to user1 he'd subscribe to private-user1 so I guess he'll see the events that user2 is triggering when sending messages to user1 too, right ? Or did I get this wrong ?
I've read in their docs that presence channel is actually a private channel extension, so I'm thinking now.. why using private channels anymore, and then, how can I notify all my friends I'm online.
But then, something else comes up in their docs , telling me that channels provide two important things (among others), from which, first is a way of filtering data and second is a way of controlling access.
How am I supposed to "filter data" since there's no link in their docs, or better, what do you have in mind for a one-to-one chat. I'm sorry if I got all their docs wrong, I had a look on their sample applications but none of them are using the one-to-one technique which I'm looking for.
I am new to Pusher and socket connections etc, but I've learned how to authenticate, how to create , detect and process the events in the channel, and I can create a simple global chat with online members, but, when it comes to private-channels I'm quite confused on how to create separate channels for two users.
Thanks in advance !
The purpose of private channels is to restrict who can subscribe to that channel. So, you can either:
Use it to ensure only a users friends can subscribe to updates
Use it for notifications only for that user
In one-to-one chat I'd suggest you choose the latter (No.2).
With this in mind I'd set out achieving one-to-one chat as follows:
The Forum
When users join the chat application they all subscribe to two channels:
private-notifications-<user_id> where user_id is their unique user ID e.g. leggetter in my case. This channel is utilised for user-specific notifications.
presence-forum for all users in that forum. The question called this presence-global.
This is achieved as follows:
var notifications = pusher.subscribe( 'private-notifications-user_one' );
var forum = pusher.subscribe( 'presence-forum' );
Upon subscription to each channel the channel authentication process will take place.
Within the forum you could have a general public chat on the presence-forum/presence-global presence channel by sending and receiving messages.
Starting one-to-one chat
When one user (user_one) wants to have a private chat with another user (user_two) you obviously need something in the UI to trigger this. Say user_one clicks on something next to user_two that indicates they want a one-to-one chat. When this happens a request should be made to the server (the authority) to indicate that user_one wants to initiate the private chat with user_two†.
Note: †if you chose a channel naming convention for one-to-one chat the private channel authentication could actually be used as the private one-to-one chat initiation
When the server receives this request it can generate a unique private channel name for this one-to-one chat. A really simple way of doing this is by concatenating the user IDs e.g. private-chat-<initiating_user>-<receiving_user> (there are other considerations e.g. maybe you want to ensure the channel name is always the same between the two users). In our simple scenario the channel name would be private-chat-user_one-user_two.
The server can then trigger a one-to-one-chat-request event on the private notification channel for each user delivering the one-to-one private chat channel name in the payload.
// Trigger event on both user channels with one call
var channels = [ 'private-notifications-user_one', 'private-notifications-user_two' ];
// Additional event data could also be sent
// e.g. more info on the initiating user
var eventData = {
'channel_name': 'private-chat-user_one-user_two',
'initiated_by': 'user_one'
'chat_with' : 'user_two'
};
pusher.trigger( channels, 'one-to-one-chat-request', eventData );
When user_one receives the one-to-one-chat-request they will subscribe to the eventData.channel_name channel and the auth process will take place for that channel.
// A lookup of private chats
// where the key is the user ID of the current user is chatting with
var privateChats = {};
notifications.bind( 'one-to-one-chat-request', function( data ) {
// MY_USER_ID would need to be stored somewhere
// and in this case the value would be 'user_one'.
// expectingChatWith should make sure user_one is waiting for
// a private chat response with the given user
if( data.initiated_by === MY_USER_ID &&
expectingChatWith( data.chat_with ) ) {
startPrivateChat( data.chat_with, data.channel_name );
}
} );
function startPrivateChat( withUserId, channelName ) {
privateChats[ withUserId ] = pusher.subscribe( channelName );
}
When user_two receives the one-to-one-chat-request the user will need to be notified about the request and either accept or decline it. If the user accepts then the client-side code simply subscribes to the channel. If the user declines then a request should be sent to the server and an event triggered on private-notifications-user_one telling them their one-to-one chat request was declined. This will allow user_one to unsubscribe from the private chat channel.
var privateChats = {};
notifications.bind( 'one-to-one-chat-request', function( data ) {
if( ... ) { ... }
// has somebody request to chat with this user?
else if( data.chatWith === MY_USER_ID ) {
// Prompt the user
// Note: more user info required
displayChatPrompt( data );
}
} );
// callback when the user accepts the chat request
function accepted( chatUserId, channelName ) {
startPrivateChat( chatUserId, channelName );
}
// the user doesn't want to chat
function declined( chatUserId ) {
// send info to the server indicating declined request
}
Private one-to-one chat success
With both user_one and user_two subscribed to private-chat-user_one-user_two they can trigger events on the channel and participate in their private one-to-one chat.