How to Configure CIDR Whitelisting for API Access Control in OpenWA

OpenWA implements CIDR whitelisting through the allowedIps array on API key entities, validating client IPs via the isIpAllowed and ipInCidr methods in AuthService to restrict HTTP API access to specific networks or exact addresses.

OpenWA (rmyndharis/OpenWA) secures its HTTP API using scoped API keys that support network-level access restrictions. Understanding how to configure CIDR whitelisting for API access control in OpenWA allows you to limit key usage to specific datacenters, VPN ranges, or individual client machines.

Understanding the Whitelist Data Model

The CIDR whitelist configuration resides on the ApiKey entity and passes through Data Transfer Objects (DTOs) during creation and updates.

Storage in the API Key Entity

The whitelist persists in src/modules/auth/entities/api-key.entity.ts as a nullable text array:

@Column({ type: 'text', nullable: true, array: true })
allowedIps: string[];

DTO Validation

The CreateApiKeyDto and UpdateApiKeyDto in src/modules/auth/dto/api-key.dto.ts expose the field for API input:

allowedIps?: string[];

IP Validation Logic in AuthService

The core validation occurs in src/modules/auth/auth.service.ts. When AuthService.validateApiKey processes a request, it extracts the client IP and delegates to the IP-whitelist guard.

The isIpAllowed Method

Located at lines 206-221, isIpAllowed iterates over the allowedIps array:

  • If an entry contains /, it treats the entry as a CIDR range and delegates to ipInCidr
  • Otherwise, it performs an exact string match against the client IP

The ipInCidr Implementation

The ipInCidr method (lines 229-247) parses the CIDR string, constructs a 32-bit network mask, and compares the numeric representation of the client IP against the network range. It handles malformed CIDR values by logging a warning and returning false.

If no entries match, the service throws UnauthorizedException('IP address not allowed').

Configuring CIDR Ranges on API Keys

You can configure CIDR whitelisting when creating or updating API keys via REST endpoints or programmatically through the NestJS service layer.

Creating a Key via REST API

Send a POST request to /api/auth/api-keys with mixed exact IPs and CIDR blocks:

POST /api/auth/api-keys
Content-Type: application/json

{
  "name": "Internal Service",
  "role": "OPERATOR",
  "allowedIps": ["10.0.0.0/24", "203.0.113.5"]
}

Updating Keys Programmatically

Use the AuthService to append new ranges to existing keys:

import { AuthService } from './auth.service';

await authService.update(keyId, {
  allowedIps: [
    ...existing.allowedIps,
    '172.16.0.0/16'
  ],
});

Manual IP Verification

You can reuse the validation logic directly for custom checks:

const clientIp = '10.0.0.42';
const whitelist = ['10.0.0.0/24'];

if (authService.isIpAllowed(clientIp, whitelist)) {
  console.log('IP allowed');
} else {
  console.log('IP rejected');
}

Extending Whitelisting in Custom Guards

For advanced use cases such as checking X-Forwarded-For headers, inject AuthService into custom guards:

@Injectable()
export class CustomIpGuard implements CanActivate {
  constructor(private readonly auth: AuthService) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const req = context.switchToHttp().getRequest();
    const ip = req.headers['x-forwarded-for']?.split(',')[0] ?? req.ip;
    const apiKey = req.apiKey;

    return apiKey.allowedIps
      ? this.auth.isIpAllowed(ip, apiKey.allowedIps)
      : true;
  }
}

Summary

  • Store whitelist entries in the allowedIps array on the ApiKey entity defined in src/modules/auth/entities/api-key.entity.ts
  • Use AuthService.isIpAllowed and ipInCidr in src/modules/auth/auth.service.ts to validate IPv4 addresses against CIDR ranges or exact matches
  • Configure CIDR whitelisting via the REST API by posting string arrays containing formats like 10.0.0.0/24 to the /api/auth/api-keys endpoint
  • Handle malformed CIDR gracefully through warning logs without crashing the validation chain
  • Note that IPv6 is not supported by the built-in logic; the documentation in docs/04-security-design.md suggests using ipaddr.js for IPv6 networks

Frequently Asked Questions

Does OpenWA support IPv6 CIDR notation?

No, the built-in ipInCidr method in src/modules/auth/auth.service.ts only handles 32-bit IPv4 masks. According to docs/04-security-design.md, you must integrate a library like ipaddr.js if you need to validate IPv6 address ranges.

What happens if I provide an invalid CIDR format?

The ipInCidr method catches parsing errors, logs a warning message, and returns false for that specific entry. The validation continues checking other entries in the allowedIps array, and only rejects the request with UnauthorizedException('IP address not allowed') if no valid matches are found.

Can I mix exact IP addresses and CIDR ranges in the same API key?

Yes, the isIpAllowed method handles both formats simultaneously. Entries without a forward slash (/) are compared as exact strings, while entries containing / are processed as CIDR ranges, allowing you to whitelist both individual servers and entire subnets in one configuration.

Where is the whitelist enforced during the request lifecycle?

The AuthService.validateApiKey method enforces the whitelist immediately after API key authentication. It extracts the client IP from the request and validates it against the key's allowedIps array before allowing access to protected endpoints.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →