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 ))
}
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
Client sends request with Authorization: Basic <credentials> header
Server extracts credentials from the Authorization header
Server validates credentials against configured user list
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:
Always use HTTPS in production to encrypt credentials in transit
Use strong passwords with mix of uppercase, lowercase, numbers, and special characters
Rotate credentials regularly especially if compromised
Limit user accounts to only what’s necessary
Use environment variables instead of command-line flags to avoid exposing credentials in process lists
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:
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