The VirtualFront project is a production-grade Single Page Application (SPA) that integrates Microsoft Teams and Azure Communication Services (ACS) to enable video calling, PSTN integration, and secure authentication via Azure Active Directory (AAD). This article provides a comprehensive analysis of the source code, including architecture, project structure, integration steps, and deployment considerations.
Table of Contents
- Introduction
- High-Level Architecture
- Detailed Project Structure
- Key Components
- Integration Steps
- Code Snippets and Token Flow
- API Endpoints
- Technologies Used
- Future Enhancements
- Conclusion
Introduction
VirtualFront is a modern web application designed to act as a virtual receptionist system. It connects a browser-based SPA with Microsoft Teams users via ACS, making it ideal for kiosk-based solutions, front-desk automation, and remote concierge systems.
Key Features:
- One-click video calls to Microsoft Teams users.
- Token exchange using Azure AD and ACS.
- PSTN calling support (dialing out to phone numbers).
- Scalable backend built with Node.js and Express.
- Frontend powered by Vanilla JavaScript and ACS SDK.
High-Level Architecture
The architecture of VirtualFront is modular, with a clear separation between the frontend, backend, and Azure services. Below is a high-level diagram:
Workflow:
- The Frontend communicates with the Backend to request ACS tokens.
- The Backend authenticates users via Azure AD, exchanges tokens, and provides the frontend with call credentials.
- The Azure Services (ACS, AAD, Graph API) handle authentication, token management, and communication.
Detailed Project Structure
The project is organized into the following directories and files:
.
├── client/ # Frontend SPA (HTML, JS, CSS)
│ ├── assets/ # Static assets (images, styles)
│ ├── app.js # Main application logic
│ └── call.js # ACS call logic
│
├── constants/ # Common constants (enums, labels)
│ └── roles.js
│
├── controllers/ # Express route controllers
│ ├── token.controller.js # Token management (ACS, AAD)
│ ├── user.controller.js # Teams users & endpoint APIs
│ └── pstn.controller.js # PSTN token and phone services
│
├── public/ # Static public directory
│ └── index.html
│
├── routes/ # API route definitions
│ ├── token.routes.js
│ ├── user.routes.js
│ └── pstn.routes.js
│
├── services/ # Service layer for Azure SDK calls
│ ├── acs.service.js
│ ├── auth.service.js
│ └── teams.service.js
│
├── utils/ # Utility helpers
│ ├── logger.js
│ └── environment.js
│
├── .env # Environment variables
├── index.js # Express server entry
├── package.json # Node dependencies
├── webpack.config.js # Frontend bundling
└── README.md # Project documentation
Key Components
1. Frontend
The frontend is implemented in Vanilla JavaScript and interacts with the Azure Communication Services SDK to manage video calls and UI interactions.
Code Snippet: Initializing the Teams Call Agent
import { CallClient } from '@azure/communication-calling';
const callClient = new CallClient();
const callAgent = await callClient.createCallAgent({ userId: '' });
callAgent.on('incomingCall', (call) => {
console.log('Incoming call:', call);
call.accept();
});
2. Backend
The backend is built using Node.js and Express. It provides APIs for fetching access tokens, validating tokens, and serving the SPA.
Code Snippet: Fetching Access Tokens
const { getAccessToken } = require('../services/auth.service');
exports.getAccessToken = async (req, res) => {
const { email, token } = req.body;
const accessToken = await getAccessToken(email, token);
res.json({ accessToken });
};
3. Services
The services directory contains the core business logic for interacting with Azure SDKs.
Code Snippet: Fetching ACS Token for Teams User
const { CommunicationIdentityClient } = require('@azure/communication-identity');
exports.getAcsToken = async (aadToken, clientId, userId, tenantId) => {
const client = new CommunicationIdentityClient(process.env.ACS_CONNECTION_STRING);
const tokenResponse = await client.getTokenForTeamsUser({
teamsUserAadToken: aadToken,
clientId,
userObjectId: userId,
tenantId,
});
return tokenResponse.token;
};
Integration Steps
1. Provision Azure Communication Services (ACS)
- Create a Communication Services resource in Azure.
- Copy the connection string.
- Enable PSTN (optional).
2. Register an Azure AD Application
- Create App Registration in Azure AD.
- Configure:
- Redirect URIs (if needed)
- Client ID, Tenant ID, Client Secret
- Add Microsoft Graph API permissions:
User.Read
Directory.Read.All
3. Enable ACS Federation in Microsoft Teams
Install-Module MicrosoftTeams
Connect-MicrosoftTeams
$resourceId = ""
Set-CsTeamsAcsFederationConfiguration -EnableAcsUsers $true -AllowedAcsResources $resourceId
Set-CsExternalAccessPolicy -Identity Global -EnableAcsFederationAccess $true
4. Configure Environment Variables
Create a .env file in the root directory:
ACS_CONNECTION_STRING=endpoint=https://.communication.azure.com/;accesskey=
AAD_CLIENT_ID=
AAD_TENANT_ID=
AAD_SECRET=
TEAMS_USER_ID=
Code Snippets and Token Flow
Backend: Exchange AAD Token for ACS Token
const { CommunicationIdentityClient } = require('@azure/communication-identity');
const client = new CommunicationIdentityClient(process.env.ACS_CONNECTION_STRING);
const tokenResponse = await client.getTokenForTeamsUser({
teamsUserAadToken: aadToken,
clientId: process.env.AAD_CLIENT_ID,
userObjectId: userId,
tenantId: process.env.AAD_TENANT_ID,
});
return tokenResponse.token;
Frontend: Initiate Call to Teams
import { CallClient } from '@azure/communication-calling';
const callClient = new CallClient();
const tokenCredential = new AzureCommunicationTokenCredential("");
const callAgent = await callClient.createCallAgent(tokenCredential);
callAgent.startCall([
{ communicationUserId: "8:acs:..." }
], { videoOptions: { localVideoStreams: [] } });
API Endpoints
POST /get-access-token
Fetches an ACS token for Teams users.
POST /get-pstn-token
Fetches a PSTN token for phone calls.
GET /endpoint
Fetches the REST API endpoint for the current environment.
Technologies Used
- Frontend: Vanilla JavaScript, Webpack, ACS Calling SDK
- Backend: Node.js, Express, Azure SDK
- Identity: Azure AD, Microsoft Graph
- Cloud: Azure Communication Services
Future Enhancements
- Add support for group calls and chat features.
- Implement a CI/CD pipeline for automated deployments.
- Enhance error handling and logging mechanisms.
- Add an admin panel for managing Teams users.
Conclusion
VirtualFront demonstrates how to build a secure and scalable communication platform by integrating Microsoft Teams and Azure Communication Services. By leveraging Azure's robust APIs and SDKs, developers can create seamless communication experiences for various use cases, such as virtual receptionists, kiosks, and remote concierge systems.
For more information, refer to:
Curious to see it in action? Explore the complete implementation and code on GitHub:
VirtualFront: Seamless Communication with Microsoft Teams via Azure Communication Services (ACS)
VirtualFront is a production-grade Single Page Application (SPA) that integrates Microsoft Teams and Azure Communication Services (ACS) to enable video calling, PSTN integration, and secure authentication via Azure Active Directory (AAD). This repository contains the source code and setup instructions to get started.
🚀 Features
- One-click video calls to Microsoft Teams users.
- Token exchange using Azure AD and ACS.
- PSTN calling support (dialing out to phone numbers).
- Scalable backend built with Node.js and Express.
- Frontend powered by Vanilla JavaScript and ACS SDK.
📂 Project Structure
├── client/ # Frontend SPA (HTML, JS, CSS)
│ ├── assets/ # Static assets (images, styles)
│ ├── app.js # Main application logic
│ └── call.js # ACS call logic
│
├── constants/ # Common constants (enums, labels)
│ └── roles.js
│
├── controllers/ # Express route controllers
│ ├── token.controller.js # Token
…