Authentication API

Secure access to your Wala Works devices with token-based authentication.

Overview

Wala Works devices support optional Bearer token authentication for API endpoints. When enabled, all API requests must include a valid authentication token.

Default state: Authentication is disabled for easy setup.

Authentication Flow

Client Request
    ↓
Include: Authorization: Bearer TOKEN
    ↓
Device validates token
    ↓
├─ Valid → Process request
└─ Invalid → Return 401 Unauthorized

Enabling Authentication

Via Web Interface

  1. Navigate to device settings
  2. Security → API Authentication
  3. Toggle "Enable Authentication"
  4. Click "Generate Token"
  5. Copy and save token securely

Via API (Before Enabling)

# Enable authentication and get initial token
curl -X POST http://192.168.1.100/api/auth/enable \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "token_name": "admin"
  }'

Response:

{
  "success": true,
  "enabled": true,
  "token": "ww_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "token_name": "admin",
  "created": "2025-11-05T14:30:00Z",
  "expires": null
}

⚠️ Important: Save this token immediately. It cannot be retrieved later.

Using Authentication

HTTP Headers

Include the Bearer token in the Authorization header:

curl -H "Authorization: Bearer ww_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" \
  http://192.168.1.100/api/status

Request Examples

MotorWala with authentication:

# Get status
curl -H "Authorization: Bearer YOUR_TOKEN" \
  http://192.168.1.100/api/status

# Open motor
curl -X POST \
  -H "Authorization: Bearer YOUR_TOKEN" \
  http://192.168.1.100/api/motor/open

# Set position
curl -X POST \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"position": 50}' \
  http://192.168.1.100/api/motor/position

RelayWala with authentication:

# Turn on relay
curl -X POST \
  -H "Authorization: Bearer YOUR_TOKEN" \
  http://192.168.1.101/api/relay/1/on

# Get status
curl -H "Authorization: Bearer YOUR_TOKEN" \
  http://192.168.1.101/api/status

Token Management

Generate New Token

# Requires existing valid token
curl -X POST http://192.168.1.100/api/auth/token \
  -H "Authorization: Bearer ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "home-assistant",
    "expires": "2026-12-31T23:59:59Z"
  }'

Response:

{
  "success": true,
  "token": "ww_b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7",
  "name": "home-assistant",
  "created": "2025-11-05T14:30:00Z",
  "expires": "2026-12-31T23:59:59Z"
}

List Active Tokens

curl -H "Authorization: Bearer ADMIN_TOKEN" \
  http://192.168.1.100/api/auth/tokens

Response:

{
  "tokens": [
    {
      "id": "1",
      "name": "admin",
      "created": "2025-01-15T10:00:00Z",
      "last_used": "2025-11-05T14:28:00Z",
      "expires": null,
      "is_admin": true
    },
    {
      "id": "2",
      "name": "home-assistant",
      "created": "2025-02-01T12:00:00Z",
      "last_used": "2025-11-05T14:29:00Z",
      "expires": "2026-12-31T23:59:59Z",
      "is_admin": false
    },
    {
      "id": "3",
      "name": "node-red",
      "created": "2025-03-10T09:00:00Z",
      "last_used": "2025-11-04T20:15:00Z",
      "expires": "2025-12-31T23:59:59Z",
      "is_admin": false
    }
  ]
}

Revoke Token

# Revoke by token ID
curl -X DELETE http://192.168.1.100/api/auth/token/2 \
  -H "Authorization: Bearer ADMIN_TOKEN"

Response:

{
  "success": true,
  "message": "Token 'home-assistant' revoked"
}

Token Properties

{
  "name": "string",        // Human-readable name
  "expires": "datetime",   // ISO 8601 or null (never)
  "is_admin": boolean,     // Can manage other tokens
  "permissions": []        // Optional: granular permissions
}

Token Permissions

Admin Tokens

Full access to all endpoints including token management:

{
  "name": "admin",
  "is_admin": true,
  "permissions": ["*"]
}

Standard Tokens

Access to device control, no token management:

{
  "name": "home-assistant",
  "is_admin": false,
  "permissions": ["read", "control"]
}

Read-Only Tokens

Status monitoring only:

{
  "name": "dashboard",
  "is_admin": false,
  "permissions": ["read"]
}

Create read-only token:

curl -X POST http://192.168.1.100/api/auth/token \
  -H "Authorization: Bearer ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "dashboard",
    "permissions": ["read"]
  }'

Integration Examples

Home Assistant

Using REST commands:

# secrets.yaml
motorwala_token: "ww_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"

# configuration.yaml
rest_command:
  open_blinds:
    url: "http://192.168.1.100/api/motor/open"
    method: POST
    headers:
      Authorization: !secret motorwala_token

  close_blinds:
    url: "http://192.168.1.100/api/motor/close"
    method: POST
    headers:
      Authorization: !secret motorwala_token

Using REST sensor:

sensor:
  - platform: rest
    name: "Blinds Position"
    resource: "http://192.168.1.100/api/status"
    headers:
      Authorization: "Bearer ww_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
    value_template: "{{ value_json.position }}"
    scan_interval: 10

Node-RED

HTTP Request node configuration:

{
  "method": "POST",
  "url": "http://192.168.1.100/api/motor/open",
  "headers": {
    "Authorization": "Bearer ww_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
  }
}

Function node to add auth:

msg.headers = {
    "Authorization": "Bearer ww_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
};
return msg;

Python

import requests

TOKEN = "ww_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
BASE_URL = "http://192.168.1.100/api"

headers = {
    "Authorization": f"Bearer {TOKEN}",
    "Content-Type": "application/json"
}

# Get status
response = requests.get(f"{BASE_URL}/status", headers=headers)
print(response.json())

# Control motor
response = requests.post(
    f"{BASE_URL}/motor/position",
    headers=headers,
    json={"position": 75}
)
print(response.json())

Node.js

const axios = require('axios');

const TOKEN = 'ww_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6';
const BASE_URL = 'http://192.168.1.100/api';

const headers = {
  'Authorization': `Bearer ${TOKEN}`,
  'Content-Type': 'application/json'
};

// Get status
async function getStatus() {
  const response = await axios.get(`${BASE_URL}/status`, { headers });
  console.log(response.data);
}

// Control motor
async function setPosition(position) {
  const response = await axios.post(
    `${BASE_URL}/motor/position`,
    { position },
    { headers }
  );
  console.log(response.data);
}

getStatus();
setPosition(75);

curl with Environment Variable

# Set token in environment
export WALA_TOKEN="ww_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"

# Use in requests
curl -H "Authorization: Bearer $WALA_TOKEN" \
  http://192.168.1.100/api/status

MQTT Authentication

MQTT uses separate username/password authentication:

Device configuration:

MQTT:
  Username: wala-devices
  Password: secure-mqtt-password
  TLS: Optional

Broker configuration (Mosquitto):

# /etc/mosquitto/mosquitto.conf
allow_anonymous false
password_file /etc/mosquitto/passwd

Create password:

sudo mosquitto_passwd -c /etc/mosquitto/passwd wala-devices
# Enter password when prompted

Home Assistant MQTT configuration:

mqtt:
  broker: 192.168.1.50
  username: wala-devices
  password: !secret mqtt_password

Security Best Practices

Token Storage

Do:

  • Store tokens in secrets management
  • Use environment variables
  • Encrypt configuration files
  • Use separate tokens per integration

Don't:

  • Hardcode tokens in scripts
  • Commit tokens to version control
  • Share tokens publicly
  • Reuse tokens across devices

Token Rotation

Periodically regenerate tokens:

# Generate new token
NEW_TOKEN=$(curl -X POST http://192.168.1.100/api/auth/token \
  -H "Authorization: Bearer $OLD_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "home-assistant", "expires": "2026-12-31"}' \
  | jq -r '.token')

# Update integrations with new token
# ...

# Revoke old token
curl -X DELETE http://192.168.1.100/api/auth/token/OLD_ID \
  -H "Authorization: Bearer $OLD_TOKEN"

Network Security

Layer security practices:

  1. Network Segmentation

    • IoT VLAN for devices
    • Firewall rules between networks
  2. HTTPS (Optional)

    • Enable TLS for encrypted communication
    • Use valid certificates
  3. VPN Access

    • Access home network via VPN
    • No direct internet exposure
  4. Firewall Rules

    # Only allow local network access
    iptables -A INPUT -s 192.168.1.0/24 -p tcp --dport 80 -j ACCEPT
    iptables -A INPUT -p tcp --dport 80 -j DROP
    

Error Responses

401 Unauthorized

Missing or invalid token:

{
  "error": "Unauthorized",
  "message": "Missing or invalid authentication token"
}

Causes:

  • Token not provided
  • Token invalid/expired
  • Token revoked
  • Authentication disabled but token sent

403 Forbidden

Token valid but insufficient permissions:

{
  "error": "Forbidden",
  "message": "Insufficient permissions for this operation"
}

Causes:

  • Read-only token attempting control
  • Non-admin token attempting token management

429 Too Many Requests

Rate limit exceeded:

{
  "error": "Too Many Requests",
  "message": "Rate limit exceeded. Try again in 60 seconds"
}

Disabling Authentication

Via API

# Requires admin token
curl -X POST http://192.168.1.100/api/auth/disable \
  -H "Authorization: Bearer ADMIN_TOKEN"

Via Web Interface

  1. Settings → Security → API Authentication
  2. Toggle "Disable Authentication"
  3. Confirm action

Emergency Disable

If locked out, use serial console:

# Connect via USB
screen /dev/ttyUSB0 115200

# In serial console
> auth disable
Authentication disabled

Troubleshooting

Token not working:

  1. Verify token is correct (no extra spaces)
  2. Check "Authorization: Bearer " prefix
  3. Ensure authentication is enabled
  4. Check token hasn't expired
  5. Verify token hasn't been revoked

Can't generate tokens:

  1. Ensure you're using admin token
  2. Check token expiry format (ISO 8601)
  3. Verify network connectivity
  4. Review device logs

Locked out of device:

  1. Use serial console to disable auth
  2. Or perform factory reset (loses all settings)
  3. Backup tokens before enabling auth

Next Steps


Security questions? Check FAQ or contact support

Previous

Next