Skip to main content

Overview

The GOWA WhatsApp API uses HTTP Basic Authentication to secure API endpoints. When enabled, all requests must include valid credentials in the Authorization header.

Enabling Authentication

Authentication is optional and disabled by default. To enable it, provide credentials when starting the server.

Command Line

Use the --basic-auth or -b flag with comma-separated username:password pairs:
./whatsapp rest --basic-auth=admin:secret123

Multiple Users

You can configure multiple users with different credentials:
./whatsapp rest --basic-auth=admin:secret123,user1:pass456,user2:pass789

Environment Variable

Set the APP_BASIC_AUTH environment variable:
export APP_BASIC_AUTH=admin:secret123,user1:pass456
./whatsapp rest
Or use a .env file:
APP_BASIC_AUTH=admin:secret123,user1:pass456
APP_PORT=3000
APP_DEBUG=true

Docker Compose

services:
  whatsapp:
    image: aldinokemal2104/go-whatsapp-web-multidevice
    environment:
      - APP_BASIC_AUTH=admin:secret123,user1:pass456
      - APP_PORT=3000
    ports:
      - "3000:3000"

Making Authenticated Requests

Using cURL

Include the -u flag with username:password:
curl -u admin:secret123 http://localhost:3000/app/devices
Or use the explicit Authorization header:
curl -H "Authorization: Basic YWRtaW46c2VjcmV0MTIz" \
  http://localhost:3000/app/devices
The Base64-encoded value YWRtaW46c2VjcmV0MTIz is admin:secret123 encoded. You can generate this using: echo -n "admin:secret123" | base64

Using JavaScript (Fetch API)

const username = 'admin';
const password = 'secret123';
const credentials = btoa(`${username}:${password}`);

const response = await fetch('http://localhost:3000/app/devices', {
  headers: {
    'Authorization': `Basic ${credentials}`
  }
});

const data = await response.json();
console.log(data);

Using Python (Requests)

import requests
from requests.auth import HTTPBasicAuth

response = requests.get(
    'http://localhost:3000/app/devices',
    auth=HTTPBasicAuth('admin', 'secret123')
)

print(response.json())

Using Go

package main

import (
    "fmt"
    "io"
    "net/http"
)

func main() {
    client := &http.Client{}
    req, _ := http.NewRequest("GET", "http://localhost:3000/app/devices", nil)
    req.SetBasicAuth("admin", "secret123")
    
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    body, _ := io.ReadAll(resp.Body)
    fmt.Println(string(body))
}

Credentials Format

Username Requirements

  • Must not contain colons (:) or commas (,)
  • Can include alphanumeric characters and special characters (except : and ,)
  • Case-sensitive

Password Requirements

  • Must not contain commas (,) when defining multiple users
  • Can contain colons (:) in the password itself
  • Case-sensitive
  • No minimum length enforced (but use strong passwords in production)

Example Valid Configurations

# Single user
--basic-auth=admin:MyStr0ng!Pass

# Multiple users
--basic-auth=admin:secret,api_user:token123,backup:P@ssw0rd!

# User with special characters (avoid colons in username)
--basic-auth=api.user:MyP@ss:with:colons

Authentication Flow

  1. Client sends request with Authorization: Basic <credentials> header
  2. Server extracts credentials from the Authorization header
  3. Server validates credentials against configured user list
  4. Access granted if credentials match, otherwise returns 401 Unauthorized

Unauthorized Response

When authentication fails, the API returns a 401 Unauthorized status:
{
  "status": 401,
  "code": "401",
  "message": "Unauthorized access",
  "results": null
}
See the Error Handling guide for more details on error responses.

Security Best Practices

Production Security Checklist:
  1. Always use HTTPS in production to encrypt credentials in transit
  2. Use strong passwords with mix of uppercase, lowercase, numbers, and special characters
  3. Rotate credentials regularly especially if compromised
  4. Limit user accounts to only what’s necessary
  5. Use environment variables instead of command-line flags to avoid exposing credentials in process lists
  6. Enable debug mode only in development (APP_DEBUG=false in production)

HTTPS with Reverse Proxy

For production deployments, use a reverse proxy like Nginx or Caddy to handle HTTPS: Nginx example:
server {
    listen 443 ssl;
    server_name api.example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
Caddy example (automatic HTTPS):
api.example.com {
    reverse_proxy localhost:3000
}

Trusted Proxies

When running behind a reverse proxy, configure trusted proxy IP ranges:
APP_TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
This ensures the API correctly identifies client IPs for logging and security.

Middleware Implementation

The authentication is implemented in the basicauth.go middleware:
func BasicAuth() fiber.Handler {
    return func(c *fiber.Ctx) error {
        token := string(c.Request().Header.Peek("Authorization"))
        if token != "" {
            ctx := context.WithValue(c.Context(), AuthorizationValue("BASIC_AUTH"), token)
            c.SetUserContext(ctx)
        }
        return c.Next()
    }
}
The middleware extracts the Authorization header and validates it against configured credentials.

Disabling Authentication

To disable authentication, simply omit the --basic-auth flag or APP_BASIC_AUTH environment variable:
./whatsapp rest
Only disable authentication in development or when using other security mechanisms (e.g., API running on localhost only, VPN-protected network, or behind an authenticated gateway).

Next Steps

Device Scoping

Learn about multi-device management

Error Handling

Handle authentication errors

Build docs developers (and LLMs) love