Express Azure AD JWT Middleware

raw JSON →
0.2.2 verified Thu Apr 23 auth: no javascript abandoned

This package provides Express middleware specifically designed for authenticating HTTP requests using JSON Web Tokens (JWTs) issued by Azure Active Directory (AAD). It streamlines the process of validating incoming JWTs and, upon successful validation, decodes the token and attaches the resulting JSON object to `req.user` (or a configurable property like `req.auth`). This allows subsequent middleware or route handlers to easily access user information for authorization and access control. The current stable version, 0.2.2, was released several years ago, indicating the project is likely no longer actively maintained. Its primary differentiation lies in its explicit focus on Azure AD JWT validation within the Express framework, simplifying integration for applications within the Microsoft ecosystem.

error Error: UnauthorizedError: No authorization token was found
cause The incoming HTTP request did not include an 'Authorization' header with a Bearer token, or the token was malformed.
fix
Ensure the client sends an 'Authorization' header in the format Authorization: Bearer <YOUR_JWT_TOKEN> for protected routes.
error Error: UnauthorizedError: invalid token
cause The provided JWT is invalid; this could be due to incorrect signature, expired token, invalid issuer, or incorrect audience.
fix
Verify that the JWT is correctly signed, has not expired, and matches the expected issuer and audience configured in the express-azure-jwt middleware options.
breaking The package is effectively abandoned. The last commit on GitHub was in January 2017, and the latest npm version (0.2.2) was published over 7 years ago. This means there will be no new features, bug fixes, or security patches, which is a significant risk for authentication middleware.
fix Consider migrating to a more actively maintained authentication library for Azure AD, such as `@azure/msal-node` or Passport.js strategies like `passport-azure-ad`.
gotcha This middleware is specifically designed for JWTs issued by Azure Active Directory. Attempting to use it with JWTs from other identity providers (e.g., Auth0, Firebase, custom JWTs) may lead to validation failures or unexpected behavior, as it relies on AAD-specific issuer and audience validation logic.
fix Ensure your application exclusively uses Azure AD as its identity provider. For other providers, use a more generic or provider-specific JWT validation library.
gotcha Due to its age and CommonJS-first design, this package may have compatibility issues or require specific configuration (e.g., `esModuleInterop` in TypeScript) when used in modern Node.js environments that default to ES Modules (ESM).
fix For new projects, prefer ESM-native libraries. If using this package, ensure your build setup correctly handles CommonJS modules or use `require()` imports directly.
gotcha The default behavior on an invalid or missing token is to throw an `UnauthorizedError`. While the README provides an example of catching this, failure to implement a global error handler for `UnauthorizedError` will result in unhandled exceptions crashing the application or returning generic server errors.
fix Always implement Express error handling middleware (`app.use(function(err, req, res, next) { ... })`) to specifically catch and gracefully handle `err.name === 'UnauthorizedError'`.
npm install express-azure-jwt
yarn add express-azure-jwt
pnpm add express-azure-jwt

This quickstart demonstrates how to set up an Express application with `express-azure-jwt` to protect routes using Azure AD JWTs, including error handling for unauthorized access and defining unprotected paths.

import express from 'express';
import jwt from 'express-azure-jwt';

const app = express();
const PORT = process.env.PORT || 3000;

// Basic JWT middleware initialization. Replace with your actual audience.
// In a real application, configuration like audience should come from environment variables.
const azureJwtMiddleware = jwt({
  audience: process.env.AZURE_AD_AUDIENCE || 'api://my-app-id'
});

// Error handling middleware for JWT validation failures
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
  if (err.name === 'UnauthorizedError') {
    console.error('Unauthorized request:', err.message);
    return res.status(401).send('Invalid or missing authentication token.');
  }
  next(err);
});

// Apply JWT authentication to most routes, but exclude '/public' and '/token'
app.use(azureJwtMiddleware.unless({ path: ['/public', '/token'] }));

// Public route, no authentication required
app.get('/public', (req, res) => {
  res.status(200).send('This is a public endpoint.');
});

// Protected route - requires a valid Azure AD JWT
app.get('/protected', (req, res) => {
  // req.user will contain the decoded JWT payload if authentication was successful
  if (!req.user) {
    return res.status(401).send('Authentication information not found.');
  }
  res.status(200).json({ message: 'Access granted to protected data!', user: req.user });
});

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
  console.log('Try accessing /public without a token.');
  console.log('Try accessing /protected with a valid Azure AD JWT in Authorization: Bearer header.');
});