Skip to content

[WhatsApp] Gateway does not resolve LID to phone number for user authorization #2991

@devyfriend

Description

@devyfriend

Summary

The Hermes Gateway does not resolve WhatsApp LID (Linked Identity Device) format to phone numbers when checking user authorization, while the WhatsApp bridge does. This causes users to be rejected at the gateway level even when their phone number is correctly configured in WHATSAPP_ALLOWED_USERS.

Environment

  • Hermes version: Latest (as of 2026-03-25)
  • Platform: WhatsApp
  • Mode: Bot

Problem Description

WhatsApp now uses LID (Linked Identity Device) format for user identification, e.g., 123456789012345@lid. The session stores mapping files between phone numbers and LIDs:

~/.hermes/whatsapp/session/lid-mapping-628123456789.json → "123456789012345"
~/.hermes/whatsapp/session/lid-mapping-123456789012345_reverse.json → "628123456789"

Current Behavior

There are two authorization layers with inconsistent handling:

1. WhatsApp Bridge (scripts/whatsapp-bridge/bridge.js, lines 192-194):

if (!msg.key.fromMe && ALLOWED_USERS.length > 0) {
  const resolvedNumber = lidToPhone[senderNumber] || senderNumber;
  if (!ALLOWED_USERS.includes(resolvedNumber)) continue;
}

The bridge correctly resolves LID to phone number using the lidToPhone mapping before checking ALLOWED_USERS.

2. Hermes Gateway (gateway/run.py):

if not self._is_user_authorized(source):
    logger.warning("Unauthorized user: %s (%s) on %s", source.user_id, source.user_name, source.platform.value)

The gateway does not resolve LID to phone number. It passes the raw source.user_id (e.g., 123456789012345@lid) to _is_user_authorized(), which checks against WHATSAPP_ALLOWED_USERS.

Result

When a user with phone number 628123456789 sends a message:

  1. ✅ Bridge allows the message (resolves LID 123456789012345 → phone 628123456789, found in allowed list)
  2. ❌ Gateway rejects the message (checks LID 123456789012345@lid against allowed list, not found)

Gateway logs:

WARNING gateway.run: Unauthorized user: 123456789012345@lid (username) on whatsapp
WARNING gateway.platforms.base: [Whatsapp] Handler returned empty/None response for 120363XXXXXXXXXXX@g.us

Workaround

Users must add both phone number and LID to WHATSAPP_ALLOWED_USERS:

WHATSAPP_ALLOWED_USERS=628123456789,123456789012345

This works but contradicts the documentation which states only phone numbers are needed:

WHATSAPP_ALLOWED_USERS=15551234567         # Comma-separated phone numbers (with country code, no +)

Expected Behavior

The gateway should resolve LID to phone number (using the same mapping the bridge uses) before checking authorization, so users only need to specify phone numbers in WHATSAPP_ALLOWED_USERS.

Suggested Fix

The gateway should:

  1. Load LID-to-phone mappings from session files (~/.hermes/whatsapp/session/lid-mapping-*.json)
  2. When checking _is_user_authorized(), if the user_id is in LID format (*@lid), resolve it to the phone number first
  3. Then check the resolved phone number against WHATSAPP_ALLOWED_USERS

Alternatively, the bridge could send the resolved phone number in the message event instead of the raw LID.

Steps to Reproduce

  1. Set up Hermes with WhatsApp bot mode
  2. Pair WhatsApp account and note your phone number (e.g., 628123456789)
  3. Set WHATSAPP_ALLOWED_USERS=628123456789 (phone number only)
  4. Send a message to the bot from that WhatsApp account
  5. Observe the gateway logs showing "Unauthorized user: XXXXXXXXX@lid"
  6. Bot does not respond

Additional Context

  • This affects both DM and group messages
  • The LID mapping files are already available in the session directory
  • This issue was discovered and verified through testing on a live system

Related Files

  • gateway/platforms/whatsapp.py - WhatsApp platform adapter
  • gateway/run.py - Gateway authorization logic
  • scripts/whatsapp-bridge/bridge.js - Bridge with working LID resolution
  • website/docs/user-guide/messaging/whatsapp.md - Documentation

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existsarea/authAuthentication, OAuth, credential poolscomp/gatewayGateway runner, session dispatch, deliveryplatform/whatsappWhatsApp Business adaptersweeper:implemented-on-mainSweeper: behavior already present on current maintype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions