feat(bot): support random token in signature verification
- Enhanced signature verification by adding support for a `random` token included in webhook headers. - Introduced logging to display signature variants for debugging purposes. - Improved webhook handling to process new `X-Nextcloud-Talk-Random` header.
This commit is contained in:
parent
33937ab115
commit
77cf4a0aed
1 changed files with 27 additions and 11 deletions
|
|
@ -56,25 +56,37 @@ conversations: dict[str, list[tuple[datetime, str, str]]] = {}
|
||||||
MAX_HISTORY = 10 # Keep last N exchanges per user
|
MAX_HISTORY = 10 # Keep last N exchanges per user
|
||||||
|
|
||||||
|
|
||||||
def verify_signature(body: bytes, signature: str) -> bool:
|
def verify_signature(body: bytes, signature: str, random: Optional[str] = None) -> bool:
|
||||||
"""Verify Nextcloud webhook signature."""
|
"""Verify Nextcloud webhook signature."""
|
||||||
if not BOT_SECRET:
|
if not BOT_SECRET:
|
||||||
log.warning("No bot secret configured, skipping signature verification")
|
log.warning("No bot secret configured, skipping signature verification")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
expected = hmac.new(
|
|
||||||
BOT_SECRET.encode(),
|
|
||||||
body,
|
|
||||||
hashlib.sha256
|
|
||||||
).hexdigest()
|
|
||||||
|
|
||||||
# Nextcloud sends: sha256=<hex>
|
# Nextcloud sends: sha256=<hex>
|
||||||
if signature.startswith("sha256="):
|
if signature.startswith("sha256="):
|
||||||
signature = signature[7:]
|
signature = signature[7:]
|
||||||
|
|
||||||
log.info(f"Signature verification: secret_len={len(BOT_SECRET)}, expected={expected[:16]}..., received={signature[:16]}...")
|
# Try different signature computation methods
|
||||||
|
# Method 1: Just body
|
||||||
|
expected1 = hmac.new(BOT_SECRET.encode(), body, hashlib.sha256).hexdigest()
|
||||||
|
|
||||||
return hmac.compare_digest(expected, signature)
|
# Method 2: random + body (if random header present)
|
||||||
|
if random:
|
||||||
|
expected2 = hmac.new(BOT_SECRET.encode(), (random.encode() + body), hashlib.sha256).hexdigest()
|
||||||
|
else:
|
||||||
|
expected2 = None
|
||||||
|
|
||||||
|
log.info(f"Signature verification: received={signature[:16]}...")
|
||||||
|
log.info(f" Method 1 (body only): {expected1[:16]}...")
|
||||||
|
if expected2:
|
||||||
|
log.info(f" Method 2 (random+body): {expected2[:16]}...")
|
||||||
|
|
||||||
|
if hmac.compare_digest(expected1, signature):
|
||||||
|
return True
|
||||||
|
if expected2 and hmac.compare_digest(expected2, signature):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def build_prompt(user_id: str, message: str) -> str:
|
def build_prompt(user_id: str, message: str) -> str:
|
||||||
|
|
@ -182,12 +194,16 @@ async def send_reply(conversation_token: str, message: str, reply_to: int = None
|
||||||
async def handle_webhook(
|
async def handle_webhook(
|
||||||
request: Request,
|
request: Request,
|
||||||
x_nextcloud_talk_signature: Optional[str] = Header(None, alias="X-Nextcloud-Talk-Signature"),
|
x_nextcloud_talk_signature: Optional[str] = Header(None, alias="X-Nextcloud-Talk-Signature"),
|
||||||
|
x_nextcloud_talk_random: Optional[str] = Header(None, alias="X-Nextcloud-Talk-Random"),
|
||||||
):
|
):
|
||||||
"""Handle incoming webhook from Nextcloud Talk."""
|
"""Handle incoming webhook from Nextcloud Talk."""
|
||||||
body = await request.body()
|
body = await request.body()
|
||||||
|
|
||||||
|
log.info(f"Headers: signature={x_nextcloud_talk_signature}, random={x_nextcloud_talk_random}")
|
||||||
|
log.info(f"Body (first 200): {body[:200]}")
|
||||||
|
|
||||||
# Verify signature
|
# Verify signature
|
||||||
if x_nextcloud_talk_signature and not verify_signature(body, x_nextcloud_talk_signature):
|
if x_nextcloud_talk_signature and not verify_signature(body, x_nextcloud_talk_signature, x_nextcloud_talk_random):
|
||||||
log.warning("Invalid webhook signature")
|
log.warning("Invalid webhook signature")
|
||||||
raise HTTPException(status_code=401, detail="Invalid signature")
|
raise HTTPException(status_code=401, detail="Invalid signature")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue