How to Build a JavaScript Chat App
This step-by-step tutorial will guide you on how to build a JavaScript chat app using CometChat's chat widget and Firebase.
App and web development have come a long way over the last few years. We use a lot of chat apps everyday. One of the most widely used features is live chat. However, do we really understand how the applications secure our messages? This tutorial helps us answer that question. Using the React CometChat UI Kit, Firebase backend services and Virgil Security, you will learn how to build end to end encrypted chat app with CometChat
Follow along the steps to build an end-to-end encrypted chat app that will allow users:
Users
Chat
Prerequisites
To follow this tutorial, you must have a degree of understanding of the general use of React.js. This will help you to improve your understanding of this tutorial.
*Note: At this time of writing this tutorial, we are using the Firebase SDK with the version @8.9.1
In this project, we will Node.js/Express framework to build the server side. We need to use the server side because we need to generate Virgil JWT Token, we will discuss about this in the following sections. To install the app dependencies for the server side, please follow the below steps:
10. Make sure to exclude **.env** in your gitIgnore file from being exposed online.
E2EE is a great way to secure your messages. It means that, when you use E2EE to encrypt your messages, no one can see the content of your message including hackers, the government, or event your company. On the other hand, E2EE is much more stronger than standard encryption methods. You can see the below example for more information.
For example, if you send or receive an email using your company’s service, and that service does not use E2EE such as Gmail, and so on. The organization can still see the content of your messages because they know about the encryption keys. Using E2EE, the service provider does not actually handle the decryption key.
The security behind end-to-end encryption is handled by using public-private key pair. For more information about public-private key pair, please follow the next section.
As mentioned above, the magic behind end-to-end encryption is using public-private key pair. The system will create the public and private cryptographic keys for each user. You can refer to the below image for more information.
The system has two users - Bob and Alice. The end-to-end encrypted system provides each with a public-private key pair. The public keys are stored on the server and their private keys are stored on their device.
If Bob would like to reply, the process will be repeated. It means that Bob will encrypt the message by using Alice’s public key and decrypt the message from Bob.
We need to use Virgil Securities for more some of reasons:
On the other hand, its libraries and UI Kits are easy to use and clean code as you can see the below code snippet.
Last but not least, Virgil Securities can be applied to different industries including healthcare, financial, automotive, cloud, internet of things, industry 4.0.
According to the requirements of the end to end encrypted chat app, you need to let users create a new account and login to the application, Firebase will be used to achieve that. Head to Firebase to create a new project and activate the email and password authentication service. This is how you do it:
To begin using Firebase, you’ll need a Gmail account. Head over to Firebase and create a new project.
Firebase provides support for authentication using different providers. For example, Social Auth, phone numbers, as well as the standard email and password method. Since you will be using the email and password authentication method in this tutorial, you need to enable this method for the project you created in Firebase, as it is by default disabled.
Under the authentication tab for your project, click the sign-in method and you should see a list of providers currently supported by Firebase.
Next, click the edit icon on the email/password provider and enable it.
Now, you need to go enable Firebase Realtime Database. We will Firebase Realtime Database to store the information of the users in the application. Please refer to the following part for more information.
Please follow the guidance from Firebase. After following all steps, you will see the database URL. If you just need to update the “FIREBASE_REALTIME_DATABASE_URL” variable in your “Constants.java” file with that value.
On the other hand, your Firebase real-time database will be expired in the future. To update the rules you just need to select the “Rules” tab and update the date/time in milliseconds as you can see in the image below.
The below images demonstrate the data structure of the application. A user should have an avatar, an email, an id. Because the end-users can log in to the application by using multiple devices. Therefore, we need to save the private key to the Virgil Security cloud and then retrieve it as needed. To do that, we need to use the keyPassword field. Actually, it is just a unique data, we use the uuid library to generate that data and save it to the Firebase Realtime Database. We will discuss about saving and retrieving the private key in the following sections.
Inside your project structure, open the index.css files and paste the codes here. index.css file will contain all CSS of the application.
The below codes initialize CometChat in your app before it spins up. The App.js file uses your CometChat API Credentials. We will get CometChat API Credentials from the .env file. Please do not share your secret keys on GitHub.
Actually, App.js does not contain only the above code. It also contains other business logic of the application. The full source code of App.js file can be found here.
You need to create a “firebase.js” file inside the “src” folder and you need to enable Firebase realtime database. This file is responsible for interfacing with Firebase authentication and database services. Also, it makes ready our google authentication service provider enabling us to sign in with google. Secret keys will be stored in the .env file. As mentioned above, please do not share your secret keys on GitHub.
The below images demonstrate the data structure of the application. A user should have an avatar, an email, an id.
The image below reveals the project structure for the server side. Make sure you see the folder arrangement before proceeding.
Now, let's make the rest of the project components as seen in the image above.
The image below reveals the project structure. Make sure you see the folder arrangement before proceeding.
Now, let's make the rest of the project components as seen in the image above.
In this tutorial, we need to use Node.js/Express framework for the server side. To initialize E3Kit in the client side, the client side has to get the Virgil JWT Token first. After that, the application has a function to return that token and that function will be passed to the initialize function. The initialize function helps us to initialize E3Kit on the client side. To create the API to return the Virgil JWT Token, please follow the below steps.
*Note: APP_ID, APP_KEY, APP_KEY_ID will be taken from the Virgil Security dashboard as mentioned above.
As you can see the above code snippet, we include virgil-sdk, virgil-crypto to generate the Virgil JWT Token. We also read the environment from the .env file. Those environment variables were taken from the Virgil Dashboard and saved to the .env file as mentioned above.
In this project, we need to communicate between component, we should avoid props drilling. We can have several solutions to avoid that. In this project, we can use React Context to pass data through the component tree without passing it down at every level. Therefore, we need to create the context.js file inside the src folder. This file will take responsibility for creating the React Context in the end to end encrypted chat application. Please. follow the below code snippet for more information. The full source code can be found here.
The App.js file is responsible for rendering different components by the given routes. For example, it will render the login page if the user has not logged in, yet or it renders the home page if the user has signed in to the system. On other hand, it will be used to initialize CometChat.
The full source code of the App.js file can be found here.
The loading component will be shown when the system performs some side effects such as interacting with Firebase or calling CometChat APIs and so on. This component will be used to increase user experience. If we do not have this component, the end-users cannot know when the data is loaded successfully.
The full source code of the loading component can be found here.
This component is responsible for authenticating our users using the Firebase google authentication service. It accepts the user credentials and either signs him up or in, depending on if he is new to our application. See the code below and observe how our app interacts with Firebase and the CometChat SDK. The full source code can be found here.
Before calling any functions from the CometChat service, please make sure that. CometChat was initialized successfully in your application. After the user has logged in successfully. He/She will be redirected to the home page. In this case, we need to store the authenticated user in the AsyncStorage for further usages. You can refer to the code snippet below to understand how to log in to the CometChat.
On the other hand, we need to integrate with E3Kit of the Virgil Security. For this reason, we need to initialize the EThree as what we have done with the CometChat. You can refer to the below code snippet for more information.
The above code snippet indicates that we need to the /virgil-jwt API endpoint to get the Virgil JWT token. After that, we define a function called getVirgilToken. This function will be passed to the window.E3kit.EThree.initialize to get the eThree object. Last but not least, we need to use the created eThree object and call the register function. The register function helps us to create the public key on the Virgil cloud and store the private key on the user’s device.
The end-user can log in to the application by using multiple devices. For this reason, we need to find a way to retrieve the private key even the end-user is using different devices to test the application. If we do not do that, the application cannot decrypt the messages, it just can work well on a single device. Fortunately, Virgil Security is providing a way to restore the private key. You can refer to this link for more information. To backup and restore the private key, you can follow the below steps:
For the full source code of the Login component, you can find from here.
In the Login component, we are using withModal as a higher-order component. This higher-order component will be used to reuse the code of showing and hiding the custom modal. In this case, we want to show the sign-up modal to let end-users register new accounts. We will discuss the withModal - higher-order component and the sign-up component in the following section.
As mentioned above, we would like to show the SignUp component as a modal. Actually, we have multiple modals in the application, and we should avoid duplicating common functionalities such as showing/hiding the modals, and so on. To reuse the common logic, we can have several options. In this project, we will create a higher-order component called “withModal”. That higher-oder component helps us to avoid duplicating code and we can customize the UI for the modals. Please follow the below code snippet for more information. The full source code can be found here.
The sign-up component will help end-users to register new accounts. This component will do two things. The first thing is to register new accounts on Firebase by using the Firebase authentication service. Aside from that, it also registers new accounts on CometChat by using the CometChat SDK. The full source code can be found here.
To create a new account from CometChat, you need to create a new user object based on the User model from CometChat. Following that, the created user will be registered on CometChat by calling the “registerUser” function from the CometChat service. Please do not forget to pass your CometChat auth key as the second parameter You can refer to the below code snippet for more information.
Before we can use the CometChat Pro React UI kit, we need to add it in our project so that we can reference it. In this case, we are using React UI Kit v3.0. To do that, follow the next steps:
As soon as the installation is completed, you now have access to all the React UI Components. The React UI kit contains different chat UI components for different purposes as you can see in the documentation here. It includes:
1. CometChatUI
2. CometChatUserListWithMessages
3. CometChatGroupListWithMessages
4. CometChatConversationListWithMessages
5. CometChatMessages
6. CometChatUserList
7. CometChatGroupList
8. CometChatConversationList
The application should support text and voice calling. For this reason, we will create the Home component and inside the Home component, we use the CometChatUI component from React UI Kit. The full source code can be found here. Please follow the below code snippet for more information.
We need to use the eThree object inside the UI kit that’s why we pass the eThree object as a prop to the CometChat UI component. Because we use eThree object in different places of the application. Hence, we store the eThree object inside the CometChatContextProvider. Please follow the below steps:
The header component will take responsibility for rendering the greeting and including the logout icon. After the end-users click on the logout icon. The application should do some clean-up actions. The full source code of the header component can be found here.
As mentioned above, after the end-users click on the logout icon, we need to do some clean-up actions. On the other hand, we need to call the logout function from the CometChat service and the cleanup function from Virgil Security. Aside from that, we also clear the authenticated information from the local storage, set the user information to null in the created React Context, and then redirect the end-users to the login page. You can refer to the below code snippet for more information.
After the end-users had left the CometChat, they cannot leave the Virgil group. For this reason, we need to hide this option. If the end-users would like to leave the group, they need to tell the admin remove them from the group. To disable the leave group option. Please open the UIKitSettings.js file and update the below code.
We are using CometChat React UI Kit. Therefore, we need to integrate the E3Kit - Virgil Security to the UI Kit. To do that, please follow the below steps:
According to the Virgil Security documentation, we use the below code snippet to encrypt the text message.
We build two kinds of messages - an unencrypted message to be rendered on the UI and encrypted message that will be sent to the API.
After calling the API, we need to decrypt the message and render it on the UI.
If the selected conversation is a group chat, we need to load the group from the Virgil Security cloud because we need to decrypt/encrypt the messages for the selected group. To do that, we create the startVirgilGroupChat function and then call it in the componentDidMount and componentDidUpdate. On the other hand, that function will be called after a new member is added/removed from the group to reload the key. Following that, the decryptUserMessage function is used to decrypt messages for the private chat and the decryptGroupMessage is used to decrypt messages for the group chat.
Wrapping Up
In conclusion, we have done an amazing job in developing an end to end encrypted chat app by leveraging React, Firebase, and CometChat UI KIt You’ve been introduced to the chemistry behind E2EE and how the CometChat UI Kit makes chat applications buildable.
If we use E2EE solutions from the Virgil Security. Other extensions of the CometChat UI Kit will not work.
You have seen how to integrate most of the CometChat functionalities such as texting and real-time messaging, voice/video call, managing users/groups. I hope you enjoyed this tutorial and that you were able to successfully build the end to end encrypted chat app. It's time to get busy and build other related applications with the skills you have gotten from this tutorial. You can start building your chat app for free by signing up to the cometchat dashboard here.
About the Author
Hiep Le is a software engineer. He takes a huge interest in building software products and is a full-time software engineer. Most of his work is focused on one thing - to help people learn.