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:
- ✅ Bridge allows the message (resolves LID
123456789012345 → phone 628123456789, found in allowed list)
- ❌ 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:
- Load LID-to-phone mappings from session files (
~/.hermes/whatsapp/session/lid-mapping-*.json)
- When checking
_is_user_authorized(), if the user_id is in LID format (*@lid), resolve it to the phone number first
- 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
- Set up Hermes with WhatsApp bot mode
- Pair WhatsApp account and note your phone number (e.g.,
628123456789)
- Set
WHATSAPP_ALLOWED_USERS=628123456789 (phone number only)
- Send a message to the bot from that WhatsApp account
- Observe the gateway logs showing "Unauthorized user: XXXXXXXXX@lid"
- 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
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
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:Current Behavior
There are two authorization layers with inconsistent handling:
1. WhatsApp Bridge (
scripts/whatsapp-bridge/bridge.js, lines 192-194):The bridge correctly resolves LID to phone number using the
lidToPhonemapping before checkingALLOWED_USERS.2. Hermes Gateway (
gateway/run.py):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 againstWHATSAPP_ALLOWED_USERS.Result
When a user with phone number
628123456789sends a message:123456789012345→ phone628123456789, found in allowed list)123456789012345@lidagainst allowed list, not found)Gateway logs:
Workaround
Users must add both phone number and LID to
WHATSAPP_ALLOWED_USERS: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:
~/.hermes/whatsapp/session/lid-mapping-*.json)_is_user_authorized(), if the user_id is in LID format (*@lid), resolve it to the phone number firstWHATSAPP_ALLOWED_USERSAlternatively, the bridge could send the resolved phone number in the message event instead of the raw LID.
Steps to Reproduce
628123456789)WHATSAPP_ALLOWED_USERS=628123456789(phone number only)Additional Context
Related Files
gateway/platforms/whatsapp.py- WhatsApp platform adaptergateway/run.py- Gateway authorization logicscripts/whatsapp-bridge/bridge.js- Bridge with working LID resolutionwebsite/docs/user-guide/messaging/whatsapp.md- Documentation