# How OpenWA Validates API Requests Using the X-API-Key Header

> Learn how OpenWA validates API requests using X-API-Key, hashing, and database checks for security. Discover theApiKeyGuard and AuthService components.

- Repository: [Yudhi Armyndharis/OpenWA](https://github.com/rmyndharis/OpenWA)
- Tags: how-to-guide
- Published: 2026-05-21

---

**OpenWA validates API requests by extracting the key from the `X-API-Key` header (or `Authorization: Bearer` fallback), hashing it with SHA-256, and verifying it against the database while checking expiration dates, IP whitelists, and role permissions through the `ApiKeyGuard` and `AuthService` components.**

The OpenWA platform secures its HTTP endpoints through a robust API key authentication system that validates every request using the `X-API-Key` header. When a client sends a request to any protected endpoint, the authentication flow orchestrated by NestJS guards ensures only authorized access through a multi-step validation process. According to the rmyndharis/OpenWA source code, this mechanism combines cryptographic hashing, database lookups, and granular permission checks to protect the WhatsApp automation API.

## The Three-Component Validation Architecture

OpenWA's authentication flow relies on three core components working in sequence to validate requests with the X-API-Key header. The **`ApiKeyGuard`** ([`src/modules/auth/guards/api-key.guard.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/modules/auth/guards/api-key.guard.ts)) acts as the entry point, extracting the header and resolving client context. The **`AuthService`** ([`src/modules/auth/auth.service.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/modules/auth/auth.service.ts)) performs the cryptographic verification and business logic checks. Finally, the **`AuthValidateController`** ([`src/modules/auth/auth-validate.controller.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/modules/auth/auth-validate.controller.ts)) exposes a diagnostic endpoint for testing key validity.

**`ApiKeyGuard`** intercepts every incoming request to protected routes (skipping those marked with `@Public()`). It extracts the raw key via `extractApiKey`, resolves the client IP address, and forwards the data to the authentication service. If the route requires specific permissions, the guard checks `@RequiredRole()` metadata against the key's authorization level.

**`AuthService.validateApiKey`** contains the core validation logic. It hashes the incoming raw key, queries the `ApiKey` entity, and enforces security constraints including expiration dates, IP whitelisting, and session restrictions. The service updates usage counters and timestamps for audit purposes upon successful validation.

**`AuthValidateController`** provides a `POST /auth/validate` endpoint that simply forwards received keys to `validateApiKey` and returns the resolved metadata, useful for debugging or UI-based key verification.

## Step-by-Step API Key Validation Process

The validation of the X-API-Key header follows a strict sequence to ensure security and traceability. Each step is designed to prevent unauthorized access while maintaining performance.

### Header Extraction and Fallback Handling

In [`src/modules/auth/guards/api-key.guard.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/modules/auth/guards/api-key.guard.ts), the `extractApiKey` method first inspects `request.headers['x-api-key']`. If this header is absent, it falls back to parsing the `Authorization` header for a `Bearer <key>` scheme. This dual-support ensures compatibility with standard HTTP client configurations while prioritizing the dedicated `X-API-Key` header.

### Cryptographic Hashing for Secure Storage

Before any database comparison occurs, `AuthService.hashKey` computes a **SHA-256** digest of the raw API key using Node.js's `createHash('sha256').update(rawKey).digest('hex')`. Only this hash is persisted in the `api_keys` table; the plaintext key never leaves the validation layer, preventing secret leakage in logs or database dumps.

### Database Validation and Revocation Checks

The service queries the `ApiKey` entity using the hash as the lookup key. It verifies the `isActive` flag to detect revoked keys and checks the optional `expiresAt` timestamp against the current time. If either check fails, the service throws an `UnauthorizedException`, immediately rejecting the request.

### IP Whitelisting and Network Constraints

If the API key defines `allowedIps`, the service invokes `isIpAllowed` to validate the request's remote IP address. This function supports both exact IP matching and **CIDR range** notation (e.g., `192.168.1.0/24`), allowing flexible network-based access control for enterprise deployments.

### Session-Specific Authorization

When `allowedSessions` is populated on the key entity, the guard extracts the `sessionId` from the route parameters and passes it to the service. The validation ensures the key is explicitly authorized for that specific WhatsApp session, preventing cross-session key reuse in multi-tenant environments.

### Role-Based Permission Enforcement

After successful key validation, the guard checks `@RequiredRole()` metadata using `AuthService.hasPermission`. The system enforces a hierarchy of **VIEWER**, **OPERATOR**, and **ADMIN** roles, rejecting requests where the key's role lacks sufficient privileges for the endpoint.

### Request Enrichment and Usage Auditing

Upon passing all checks, the validated `ApiKey` object is attached to the request as `request.apiKey`, allowing downstream controllers to access metadata without re-validating. The service increments `usageCount` and updates `lastUsedAt`, creating a complete audit trail for security monitoring.

## Implementation Code Examples

### Authenticating with cURL and X-API-Key Headers

Send a request to any protected endpoint by including the key in the header:

```bash
curl -X GET "http://localhost:2785/api/v1/contacts" \
     -H "Content-Type: application/json" \
     -H "X-API-Key: your-api-key"

```

If the key is valid, the API returns the requested data; otherwise, it returns a `401 Unauthorized` status.

### JavaScript SDK Integration

The OpenWA SDK automatically injects the X-API-Key header from configuration:

```javascript
import OpenWA from 'openwa';

const client = new OpenWA({
  baseUrl: 'http://localhost:2785',
  apiKey: 'your-api-key',
});

await client.get('/api/v1/contacts');

```

### Validating Keys via the Diagnostic Endpoint

Test key permissions and restrictions without hitting production data:

```bash
curl -X POST "http://localhost:2785/auth/validate" \
     -H "Content-Type: application/json" \
     -H "X-API-Key: your-api-key"

```

This returns the full `ApiKey` entity—including role, IP restrictions, and usage statistics—if the key passes all validation checks.

## Summary

- **Dual header support**: OpenWA accepts API keys via `X-API-Key` or `Authorization: Bearer` headers, extracted in `ApiKeyGuard`.
- **SHA-256 hashing**: Raw keys are hashed before database comparison, ensuring secrets are never stored or transmitted in plaintext.
- **Multi-layer validation**: The `AuthService` checks expiration, IP whitelists (including CIDR), session restrictions, and role hierarchies.
- **Audit trail**: Successful validations update `usageCount` and `lastUsedAt` timestamps for security monitoring.
- **Request enrichment**: Validated keys attach to the request object as `request.apiKey` for downstream access.

## Frequently Asked Questions

### What happens if the X-API-Key header is missing?

If the `X-API-Key` header is absent, OpenWA attempts to extract the key from the `Authorization: Bearer <key>` header as a fallback. If neither header contains a valid key format, the `ApiKeyGuard` throws an `UnauthorizedException` and returns a `401` status code, blocking access to the endpoint.

### How does OpenWA store API keys securely?

OpenWA never stores the plaintext API key. In [`src/modules/auth/auth.service.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/modules/auth/auth.service.ts), the `hashKey` method computes a SHA-256 digest of the raw key, and only this hexadecimal hash is persisted in the database. When validating requests, the incoming key is hashed using the same algorithm and compared against the stored hash.

### Can I restrict API keys to specific IP addresses?

Yes, the `ApiKey` entity supports an `allowedIps` array that enforces IP-based restrictions during validation. The `isIpAllowed` method in `AuthService` validates client IPs against this list, supporting both exact matches and CIDR range notation (such as `10.0.0.0/8`), allowing fine-grained network access control.

### What is the difference between OPERATOR and ADMIN roles?

OpenWA implements a role hierarchy where **ADMIN** has full system access, **OPERATOR** can perform actions but may lack destructive or configuration-level permissions, and **VIEWER** has read-only access. The `AuthService.hasPermission` method compares the key's role against `@RequiredRole()` metadata on controllers, rejecting requests where the key's authorization level is insufficient.