What is Zero Trust?
Zero Trust Architecture (ZTA) is a security model based on the principle "never trust, always verify." Traditional security models assume that everything inside the corporate network is trustworthy. Zero Trust assumes that threats exist both outside and inside the network, so every request must be authenticated, authorized, and encrypted regardless of where it comes from.
The concept was originally coined by Forrester Research and has been widely adopted following major breaches where attackers gained access to internal networks and moved laterally without restriction. In a zero trust model, there is no implicit trust based on network location — a request from inside the office is treated with the same scrutiny as a request from the internet.
Zero Trust Core Principles
- Verify Explicitly: Always authenticate and authorize based on all available data points including user identity, location, device health, service or workload, data classification, and anomalies.
- Use Least Privilege Access: Limit user access with just-in-time and just-enough-access (JIT/JEA), risk-based adaptive policies, and data protection to protect both data and productivity.
- Assume Breach: Minimize blast radius and segment access. Verify end-to-end encryption, use analytics to detect and respond to anomalies in real time.
Implementing Zero Trust in Web Applications
For web developers, zero trust means every API call between services must be authenticated and authorized, even if both services are running in the same cluster. This is a fundamental shift from the traditional approach where services behind a firewall trusted each other implicitly.
// Zero Trust service-to-service communication
import jwt from "jsonwebtoken";
import crypto from "crypto";
// Each service has its own identity and credentials
interface ServiceIdentity {
serviceId: string;
serviceName: string;
allowedScopes: string[];
}
// Service-to-service JWT authentication
class ServiceAuth {
private privateKey: string;
private trustedPublicKeys: Map<string, string>;
constructor(privateKey: string) {
this.privateKey = privateKey;
this.trustedPublicKeys = new Map();
}
// Create a signed request token for outgoing calls
createServiceToken(targetService: string, scopes: string[]): string {
return jwt.sign(
{
iss: process.env.SERVICE_ID,
aud: targetService,
scopes,
jti: crypto.randomUUID(),
},
this.privateKey,
{ algorithm: "RS256", expiresIn: "30s" } // Very short-lived
);
}
// Verify incoming service-to-service requests
verifyServiceToken(token: string): ServiceIdentity {
const decoded = jwt.decode(token, { complete: true });
if (!decoded) throw new Error("Invalid token");
const issuer = (decoded.payload as any).iss;
const publicKey = this.trustedPublicKeys.get(issuer);
if (!publicKey) throw new Error(`Unknown service: ${issuer}`);
const verified = jwt.verify(token, publicKey, {
algorithms: ["RS256"],
audience: process.env.SERVICE_ID,
}) as any;
return {
serviceId: verified.iss,
serviceName: verified.iss,
allowedScopes: verified.scopes,
};
}
}
// Zero Trust middleware: verify every request
function zeroTrustMiddleware(requiredScope: string) {
return async (req: Request, res: Response, next: NextFunction) => {
const token = req.headers["x-service-token"] as string;
const userToken = req.headers.authorization?.replace("Bearer ", "");
// Layer 1: Verify service identity
if (token) {
try {
const service = serviceAuth.verifyServiceToken(token);
if (!service.allowedScopes.includes(requiredScope)) {
return res.status(403).json({ error: "Scope not permitted" });
}
req.callingService = service;
} catch (err) {
return res.status(401).json({ error: "Invalid service token" });
}
}
// Layer 2: Verify user identity (if present)
if (userToken) {
try {
req.user = verifyAccessToken(userToken);
} catch (err) {
return res.status(401).json({ error: "Invalid user token" });
}
}
// Layer 3: At least one identity must be verified
if (!req.callingService && !req.user) {
return res.status(401).json({ error: "Authentication required" });
}
// Layer 4: Log the access for audit
await auditLog.record({
action: requiredScope,
serviceId: req.callingService?.serviceId,
userId: req.user?.id,
resource: req.url,
timestamp: new Date().toISOString(),
ip: req.ip,
});
next();
};
}
Microsegmentation
Microsegmentation is a key component of zero trust. Instead of having a flat network where any service can talk to any other service, you define explicit communication policies. Each service can only communicate with the specific services it needs to, on the specific ports and protocols it requires, and only for the specific operations that are authorized.
// Define service communication policies
const servicePolicies: Record<string, ServicePolicy> = {
"user-service": {
canCallServices: ["database-service", "email-service", "cache-service"],
exposedEndpoints: [
{ path: "/api/users", methods: ["GET", "POST"], requiredScopes: ["users:read", "users:write"] },
{ path: "/api/users/:id", methods: ["GET", "PUT", "DELETE"], requiredScopes: ["users:read", "users:write"] },
],
},
"order-service": {
canCallServices: ["user-service", "payment-service", "inventory-service"],
exposedEndpoints: [
{ path: "/api/orders", methods: ["GET", "POST"], requiredScopes: ["orders:read", "orders:write"] },
],
},
"payment-service": {
canCallServices: ["database-service"], // Payment service is isolated
exposedEndpoints: [
{ path: "/api/payments", methods: ["POST"], requiredScopes: ["payments:process"] },
],
},
};
// Enforce communication policies
function enforceServicePolicy(
callingService: string,
targetService: string,
endpoint: string,
method: string
): boolean {
const policy = servicePolicies[callingService];
if (!policy) return false;
// Check if caller is allowed to talk to target
if (!policy.canCallServices.includes(targetService)) {
logger.warn(`Policy violation: ${callingService} attempted to call ${targetService}`);
return false;
}
return true;
}
Device Trust and Context-Aware Access
Zero trust extends beyond service-to-service communication. When users access applications, the system should evaluate the trustworthiness of their device and the context of their request. Is the device managed? Is the OS up to date? Is the request coming from an unusual location? These signals inform the access decision.
// Context-aware access control
interface AccessContext {
userId: string;
ip: string;
userAgent: string;
geoLocation?: { country: string; city: string };
deviceFingerprint?: string;
requestTime: Date;
}
async function evaluateAccessRisk(context: AccessContext): Promise<{
riskLevel: "low" | "medium" | "high";
requireMFA: boolean;
actions: string[];
}> {
const riskSignals: string[] = [];
// Check for impossible travel
const lastLogin = await getLastLogin(context.userId);
if (lastLogin && context.geoLocation) {
const timeDiff = context.requestTime.getTime() - lastLogin.time.getTime();
const distance = calculateDistance(lastLogin.location, context.geoLocation);
const maxPossibleSpeed = distance / (timeDiff / 3600000); // km/h
if (maxPossibleSpeed > 1000) {
riskSignals.push("impossible_travel");
}
}
// Check for new device
const knownDevices = await getKnownDevices(context.userId);
if (!knownDevices.includes(context.deviceFingerprint || "")) {
riskSignals.push("new_device");
}
// Check for unusual time
const hour = context.requestTime.getHours();
const userTimezone = await getUserTimezone(context.userId);
if (hour < 5 || hour > 23) {
riskSignals.push("unusual_time");
}
// Check for known malicious IPs
const isMalicious = await checkThreatIntelligence(context.ip);
if (isMalicious) {
riskSignals.push("malicious_ip");
}
// Calculate risk level
const riskLevel = riskSignals.length >= 3 ? "high" :
riskSignals.length >= 1 ? "medium" : "low";
return {
riskLevel,
requireMFA: riskLevel !== "low",
actions: riskSignals.length >= 3
? ["block", "notify_security"]
: riskSignals.length >= 1
? ["require_mfa", "log_suspicious"]
: ["allow"],
};
}
Security Warning: Zero Trust Implementation
- Do not rely on network perimeter alone: VPNs and firewalls are not sufficient. You must verify identity at every layer.
- Encrypt all internal traffic: Use mTLS between services, even within your private network.
- Implement continuous verification: Do not just verify at login — re-evaluate trust throughout the session.
- Monitor everything: Zero trust requires comprehensive logging and anomaly detection to be effective.
Zero Trust Implementation Roadmap
- Identify your protect surface: Map your critical data, applications, assets, and services.
- Map transaction flows: Understand how traffic moves across your network.
- Architect a zero trust network: Define microsegmentation policies.
- Create zero trust policies: Who, what, when, where, why, and how for each resource.
- Monitor and maintain: Continuously inspect and log all traffic, update policies.