Azure Communication Services- Explore Chat SDK

Manish Saluja
8 min readDec 30, 2020

Azure Communication Services (ACS) makes it easy for developers to add chat, SMS text message, voice and video calling capabilities to websites, desktop applications and mobile apps with just a few lines of code. While developer friendly APIs and SDKs make it easy to create personalized communication experiences quickly, without having to worry about complex integrations. These capabilities can be used across devices and platforms, using the same reliable and secure infrastructure that powers Microsoft Teams.

In the previous blog Fully Managed Communication Platform — Azure Communication Service, we have learned how to leverage the Azure Portal to create ACS resource. Now let’s explore ACS SDK’s which we shall leverage in building simple chat solution.

Outlining the Use Case

Most of the enterprise need to build interactive chat, voice and video solution for web, desktop, or mobile applications. In other way we can say we need to have chat functionality in existing/new applications. Let’s take a scenario where we have an web application in which one user want to start a chat thread with another user/group.

While this is a scenario for the series, objective of this blog is to explore ACS SDK’s.

Minimalist

  • Don’t start with ground zero.
  • Use SDKs & APIs available for in-app chat that let one work with easy-to-understand primitives like users & messages, instead of low-level protocols.
  • Keep messages in chat flowing without losing a message.
  • Build chat experience to keep participants/user safe and adhere to all compliance needs such as HIPAA, GDPR and more.
  • Secure — multi-layered protection with built-in security controls including network security and encryption.
  • Collaboration — Enable group chats or one-one chats.
  • Suffice basic chat requirements like message read status & message type indicator.

Start from the seed

As a developer, before hitting the ground, we always want to explore ACS SDKs and APIs. ACS offers six categories.

1. Azure Resource Manager (Azure.ResourceManager.Communication) : for provisioning and managing Communication service resources.

2. Common (Azure.Communication.Common): for providing base types for other client libraries.

3. Administration (Azure.Communication.Administration): for managing users, access tokens, and phone numbers, allocate standards-compliant STUN and TURN servers.

4. Chat (Azure.Communication.Chat): for adding real-time text based chat to the applications. Chat JavaScript client library includes real-time signaling. This allows clients to listen for real-time updates and incoming messages to a chat thread without having to poll the APIs.

5. SMS (Azure.Communication.SMS): for sending and receiving Send and SMS messages.

6. Calling (Azure.Communication.Calling): for Leveraging voice, video, screen-sharing, and other real-time data communication capabilities.

These six categories client library packages are mostly available in JavaScript, .Net, Python, Java SE, iOS, Andriod. One can choose any based on the preferred landscape.

Deep dive into ACS-SDK’s

For our scenario we shall explore JavaScript SDK and below three packages

  1. Administration (Azure.Communication.Administration)
  2. Common (Azure.Communication.Common)
  3. Chat (Azure.Communication.Chat)

Let’s start with classes and method that we shall need from these packages.

Package: Administration

Class:CommunicationIdentityClient: Client class for interacting with Azure Communication Services User Token ManagementCONSTRUCTORSCommunicationIdentityClient(string, CommunicationIdentityOptions)MethodscreateUserissueToken

Package: Common

Class:AzureCommunicationUserCredential: The CommunicationUserCredential implementation with support for proactive token refresh.CONSTRUCTORSAzureCommunicationUserCredential(RefreshOptions)

Package: Chat

Class:ChatClient: The client to do chat operations.CONSTRUCTORSChatClient(string, CommunicationUserCredential, ChatClientOptions)MethodscreateChatThreadClass:ChatThreadClient: The client to do chat operations.CONSTRUCTORSChatThreadClient(string, string, CommunicationUserCredential,ChatThreadClientOptions)MethodsaddMemberssendMessagelistMessagesgetMessages

Now, we have explored the API. Let’s use these as a core component of our scenario.

Back to the drawing board

Broadly we will follow below sequence of the steps:

  • Setup ACS and get keys.
  • Get tokens and create users.
  • Create chatclient and chat thread.
  • Explore API using postman.
Azure Communication Service — information flow

Setup ACS and get keys

Follow the previous blog and create a ACS resource. Get the access keys to authorize APIs calls when one uses the Communication Services SDKs.

Azure Communication Services — Keys

See the code in Action

Once we have created the resource, now we need to create a user which will be responsible for creating the chatclient and chat thread. To implement this, we shall use a sample code published on git hub. So, create a folder and navigate to this.

Now run git clone https://github.com/salujamanish/ACS-JS-blog2-samplecode.git. Connection String of ACS resource obtained from would be required to create users and get token. So, set the environment variable with name COMMUNICATION_SERVICES_CONNECTION_STRING with connection string.

It’s time to create users and get token. For this go to the user-mgt folder, run the command npm install. Execute following node command from user-mgt folder to run the code node ./user-mgt.js run this command twice to create two different users. This shall return userId and Access Token. Save these values for further steps.

Next step is to set the environment variables USER1_ID, USER2_ID, USER_ACCESS_TOKEN with value received in previous step. Also set the environment variables USER1_DISPLAY_NAME and USER2_DISPLAY_NAME values with any display name of members of the chat.

Switch the path from user-mgt to chat folder, run the command npm install.

Execute following command from chat folder to run the code npx webpack-dev-server --entry ./client.js --output bundle.js --debug --devtool inline-source-map.

Open browser and navigate to http://localhost:8080/. In the developer tools console within browser, you should see following:

Chat Application Output

Let’s deep dive into the code!

First step is to create identities(users) and manage access tokens. The access token let chat and calling client libraries authenticate directly against Azure Communication Services. To initialize the Communication Services client libraries on client devices, access tokens are used.

We need to add require call to load CommunicationIdentityClient.

const { CommunicationIdentityClient } = require(‘@azure/communication-administration’);

To authenticate the client, we first initialize a CommunicationIdentityClient with our ACS Connection string

const client = new CommunicationIdentityClient(ConnectionString);

Users created are maintained in lightweight identity directory, to create a new entry in directory with unique id, we use createUser method.

let user = await client.createUser();

Once identity(user) is created then we issue access token to user using issueToken method, the method also takes in a list of communication token scopes. Scope options include:

  • chat (Chat)
  • pstn (Public switched telephone network)
  • voip (Voice over IP)
let tokenResponse = await client.issueToken(user, [“chat”]);

Create chatclient and chat thread

We need Communication Services client libraries, let’s add these below packages to our client application.

  • @azure/communication-common
  • @azure/communication-chat

Let’s touch some Chat key concepts before we begin further.

A chat conversation is represented by thread. In a thread each user is called a thread member. Thread member can chat with one another in 1:1 or can form group 1: N for group chat.

Chat Client provides asynchronous methods to create and delete a thread. To create chat client, we need ACS endpoint that we have captured from keys and access token for the user. We need AzureCommunicationUserCredential class from the Common client library to pass the token.

// unique Azure Communication service endpoint
let endpointUrl = process.env['ACS_ENDPOINT_URL'];
let userAccessToken = process.env['USER_ACCESS_TOKEN'];
let chatClient = new ChatClient(ACSendpointUrl, new AzureCommunicationUserCredential(userAccessToken));

Once we have Azure Communication Chat client created next, we shall use createThread method to create a chat thread. createThreadRequest is used to describe the thread request:

- Use topic to give a topic to this chat.

- Use members to list the members to be added to the chat thread.

async function createChatThread() {let createThreadRequest = {topic: 'Preparation for upcoming hack',members: [{user: { communicationUserId: user1_id },displayName: user1_displayname}, {user: { communicationUserId: user2_id },displayName: user2_displayname}]};let chatThreadClient= await chatClient.createChatThread(createThreadRequest);let threadId = chatThreadClient.threadId;return threadId;}

Now for performing operations like add members, send messages etc on the created thread using its threadId call getChatThreadClient method which shall returns a chatThreadClient on which we can perform these operations.

let chatThreadClient = await chatClient.getChatThreadClient(threadId);

Now let’s add user as member to chat Thread, use method addMembers

addMembersRequest describes the request object wherein members lists the members to be added to the chat thread.

let addMembersRequest =
{
members: [
{
user: { communicationUserId: user2_id },
displayName: user2_id
}
]
};
await chatThreadClient.addMembers(addMembersRequest);

Now we have our members added to the chat thread, let’s start sending the messages, we need to use sendMessage method to the chat thread which is identified by unique threadId.

let sendMessageRequest =
{
content: 'Hello ! Shall I schedule a meeting for tomorrow?'
};
let sendMessageOptions =
{
priority: ‘Normal’,
senderDisplayName : user1_displayname
};
let sendChatMessageResult = await chatThreadClient.sendMessage(sendMessageRequest, sendMessageOptions);let messageId = sendChatMessageResult.id;

So, we just had our logic to send the messages, lets now receive these chat message from chat thread. ACS support real time signalling so either you can subscribe to chat related events like ChatMessageReceived or you can also poll and retrieve chat messages using listMessages method at specified interval.

// open notifications channel
await chatClient.startRealtimeNotifications();
// subscribe to new notification
chatClient.on(“chatMessageReceived”, (e) => {
});

OR

let pagedAsyncIterableIterator = await chatThreadClient.listMessages();
let nextMessage = await pagedAsyncIterableIterator.next();
while (!nextMessage.done) {
let chatMessage = nextMessage.value;
nextMessage = await pagedAsyncIterableIterator.next();
}

listMessages method returns the latest version of the message, including any edits or deletes that happened to the message using updateMessage and deleteMessage methods.

For real time signalling needs, chat client library allows to listen to real time updates and incoming messages to a chat thread without having to poll API. Events which are supported are.

  • ReadReceiptReceived
  • TypingIndicatorReceived
  • ChatMessageEdited
  • ChatMessageDeleted
  • ChatMessageReceived

We can also have Azure Event Grid subscribe to the above chat related events by integrating ACS with Azure Event Grid to deliver real-time event notifications in a reliable, scalable, and secure manner. I shall cover in more detail about this integration in coming blogs.

We can also use cognitive services with chat client library to enable intelligent features like chat with each other in different language. For this, we would just need to have our trusted service act as a member of chat thread. This service will then listen to messages being exchanged by other members and shall call Cognitive API to translate the content to desired language. I shall talk about it in more details in coming blogs.

Explore API using postman

Now let’s explore API’s end point to get message and thread details using API client, here I am using Postman.

ACS has exposed REST APIs, these are service endpoints that support sets of HTTP operations (methods) which provides CRUD (Create, Read, Update & Delete) access to the ACS resource. We will explore one end point which shall retrieve the messages of chat thread. For this we shall need Access token of the valid user who is part of chat thread and chatthreadID.

In previous action we have retrieved both, let’s use those here in our API client.

We will use below URI to get list of messages from thread.

GET {endpoint}/chat/threads/{chatThreadId}/messages?api-version=2020–09–21-preview2

URI Parameter

  • endpoint- The endpoint of the ACS resource.
  • chatThreadId- The thread id of the message.

Request Header

· Authorization- An ACS user access token.

Chat Thread messages

The response includes all messages which are either system actions (add, remove users, topic update etc) or send by users. We can differentiate between these two using “type” and “senderId” values. For system actions senderId is same as chatthreadID and type starts with “ThreadActivity/”

Summary

Azure Communication Services (ACS) provides a managed platform and communication APIs to build real-time voice, video, SMS, and Chat functionality to solution at scale. In this post, we have explored Azure communication service javascript SDK and how we can build a simple chat application.

In the next blog, we shall explore chat application with User Experience.

--

--

Manish Saluja

A curious technology enthusiast with deep expertise in designing, developing and architecting cloud solutions for Public Cloud, Private clouds & Hybrid Clouds.