This guide shows how to protect Express API routes using protectApi() from the MonoCloud Backend Node SDK.
You can protect routes globally, per-route, or combine both approaches with scope and group-based authorization.
This guide assumes you've completed the Express quickstart or the installation guide.
You should already have:
@monocloud/backend-node SDK installed.envApply protectApi() as application-level middleware to protect all routes.
import "dotenv/config";
import express from "express";
import {
protectApi,
type AuthenticatedExpressRequest,
} from "@monocloud/backend-node/express";
const app = express();
const protect = protectApi();
app.use(express.json());
app.use(protect());
app.get("/api/data", (req, res) => {
const { claims } = req as AuthenticatedExpressRequest;
res.json({ claims });
});
app.listen(3000);
How it works:
protectApi() creates a middleware factory from environment variablesprotect() returns Express middleware that validates the Bearer tokenAuthorization: Bearer <token> headerreq.claimsApply the middleware to specific routes instead of globally.
import "dotenv/config";
import express from "express";
import {
protectApi,
type AuthenticatedExpressRequest,
} from "@monocloud/backend-node/express";
const app = express();
const protect = protectApi();
app.use(express.json());
// Public route — no token required
app.get("/api/public", (req, res) => {
res.json({ message: "Public data" });
});
// Protected route — requires a valid access token
app.get("/api/protected", protect(), (req, res) => {
const { claims } = req as AuthenticatedExpressRequest;
res.json({ claims });
});
app.listen(3000);
Pass scopes to protect() to require specific access token scopes.
app.get("/api/admin", protect({ scopes: ["write"] }), (req, res) => {
const { claims } = req as AuthenticatedExpressRequest;
res.json({ claims });
});
Behavior:
401 Unauthorized if the token is missing or invalid403 Forbidden if the token is valid but lacks the required scopesPass groups to protect() to require specific group memberships.
app.get("/api/team", protect({ groups: ["engineering"] }), (req, res) => {
const { claims } = req as AuthenticatedExpressRequest;
res.json({ claims });
});
Behavior:
401 Unauthorized if the token is missing or invalid403 Forbidden if the token is valid but the user is not in the required groupYou can apply global token validation and add scope or group requirements on specific routes.
import "dotenv/config";
import express from "express";
import {
protectApi,
type AuthenticatedExpressRequest,
} from "@monocloud/backend-node/express";
const app = express();
app.use(express.json());
const protect = protectApi();
// All routes require a valid access token
app.use(protect());
// Any authenticated user can access this route
app.get("/api/data", (req, res) => {
const { claims } = req as AuthenticatedExpressRequest;
res.json({ claims });
});
// Only users with the write scope and in the engineering group can access this route
app.get("/api/admin", protect({ scopes: ["write"], groups: ["engineering"] }), (req, res) => {
const { claims } = req as AuthenticatedExpressRequest;
res.json({ claims });
});
app.listen(3000);
| Scenario | Status code | Response |
|---|---|---|
| Missing or invalid token | 401 | { "message": "unauthorized" } |
| Valid token, missing scopes | 403 | { "message": "forbidden" } |
| Valid token, missing groups | 403 | { "message": "forbidden" } |
| Valid token, authorized | — | Route handler executes normally |