Identity is one of the most important security layers of modern systems. Modern apps must connect to numerous services, making a centralized and stable login system essential.
In this context, Microsoft 365 login is a logical choice for enterprise systems. Azure provides a standardized identity platform, eliminating the need to build authentication mechanisms from scratch.
Overall
At the high level, ExpressJS only acts as the client. Azure AD is the main entity, acting as the identity provider. The browser only handles redirects, while all sensitive processing, such as exchanging code for tokens, takes place in the backend.
The basic flow would be:
User → ExpressJS → Microsoft login → ExpressJS callback → session creation
Most importantly, the token never appears on the frontend. This is extremely important from a security perspective.
Setting up Azure AD
First, create a new application in Azure Active Directory via the Azure Portal.
Then create a Client Secret. Simply put, this is the "password" for the backend.
Finally, we will have three values; these three are the backbone of the entire login process:
- Client ID – app identifier
- Tenant ID – organization identifier
- Client Secret – backend authentication
MSAL node configuration
Microsoft provides @azure/msal-node so developers don't have to manually code OAuth2. MSAL handles the headaches of code generation, token changes, token caching, and token refresh.
Installation:
npm install express @azure/msal-node express-session dotenv
Basic configuration:
// msalConfig.js
require("dotenv").config();
module.exports = {
auth: {
clientId: process.env.CLIENT_ID,
authority: "https://login.microsoftonline.com/" + process.env.TENANT_ID,
clientSecret: process.env.CLIENT_SECRET
}};
The Authority URL simply tells MSAL which tenant we are authenticating with.
After defining the config, we will create the other file to initialize the instance to use in the project
// msalClient.js
const { ConfidentialClientApplication } = require("@azure/msal-node");
const msalConfig = require("../config/msalConfig");
const cca = new ConfidentialClientApplication(msalConfig);
module.exports = cca;
Scope: Request only what we need
Scope refers to access permissions. It determines what the app can do on behalf of the user.
Here are some common scopes:
- user.read – read basic profiles
- mail.read – read email
- files.read – read OneDrive files
The first time a user logs in, they will see a consent screen. This is very good, as it helps them know what permissions the app is requesting.
Actual login flow
Here, we use the OAuth2 authorization code flow – almost the default standard for backends.
The token is not exposed to the frontend. There is a refresh token widely accepted by enterprises
Route /login
const cca = require("./services/msalClient");
app.get("/login", async (req, res) => {
const url = await cca.getAuthCodeUrl({
scopes: ["user.read"],
redirectUri: "http://localhost:3000/redirect"
});
res.redirect(url);
});
This route only serves to redirect the user to the Microsoft login page.
Note: The redirectUri in the code must match the Redirect URI declared in Azure AD.
If they don't match, the login will fail.
Route /redirect
const cca = require("./services/msalClient");
app.get("/redirect", async (req, res) => {
const tokenResponse = await cca.acquireTokenByCode({
code: req.query.code,
scopes: ["user.read"],
redirectUri: "http://localhost:3000/redirect"
});
req.session.user = tokenResponse.account;
req.session.accessToken = tokenResponse.accessToken;
res.redirect("/dashboard");
});
This is the main processing point: the backend exchanges the code for a token and then saves the session.
Sessions and Middleware
After establishing the session, protecting the route with middleware is all we need to do.
function requireAuth(req, res, next) {
if (!req.session.user) {
return res.redirect("/login");
}
next();
}
Conclusion
Microsoft 365 login is becoming the standard for modern enterprise systems. Instead of managing users, passwords, and complex security rules ourselves, we can directly use Azure Active Directory as a trusted identity provider.
In practice, this offers better security, less maintenance, and a login system that can scale across the organization without significant changes.
Whether you need scalable software solutions, expert IT outsourcing, or a long-term development partner, ISB Vietnam is here to deliver. Let’s build something great together—reach out to us today. Or click here to explore more ISB Vietnam's case studies.
[References]





