|
|
|
@ -115,25 +115,53 @@ class PlugNMeetWebhookAPIView(APIView): |
|
|
|
return False |
|
|
|
|
|
|
|
body_bytes = request.data |
|
|
|
auth_header = request.headers.get('Authorization') or request.META.get('HTTP_AUTHORIZATION', '') |
|
|
|
|
|
|
|
logger.info(f"🔍 [PlugNMeet Webhook] Verify Signature details:") |
|
|
|
logger.info(f" - Hash-Token (first 30 chars): {hash_token[:30]}... (length: {len(hash_token)})") |
|
|
|
logger.info(f" - Authorization (first 30 chars): {auth_header[:30]}... (length: {len(auth_header)})") |
|
|
|
logger.info(f" - Body bytes length: {len(body_bytes)}") |
|
|
|
if len(body_bytes) > 0: |
|
|
|
logger.info(f" - Body preview (first 100 bytes): {body_bytes[:100]}") |
|
|
|
|
|
|
|
# 1. Try JWT verification (PlugNMeet production standard) |
|
|
|
try: |
|
|
|
# A JWT typically consists of three segments separated by dots |
|
|
|
if len(hash_token.split('.')) == 3: |
|
|
|
decoded = jwt.decode(hash_token, api_secret, algorithms=['HS256']) |
|
|
|
logger.info(" - Attempting JWT decode on Hash-Token...") |
|
|
|
decoded = jwt.decode( |
|
|
|
hash_token, |
|
|
|
api_secret, |
|
|
|
algorithms=['HS256'], |
|
|
|
options={ |
|
|
|
"verify_signature": True, |
|
|
|
"verify_exp": False, |
|
|
|
"verify_nbf": False, |
|
|
|
"verify_iat": False, |
|
|
|
"verify_aud": False, |
|
|
|
"verify_iss": False |
|
|
|
} |
|
|
|
) |
|
|
|
logger.info(f" - Decoded JWT claims: {list(decoded.keys())}") |
|
|
|
token_sha256 = decoded.get('sha256') |
|
|
|
if token_sha256: |
|
|
|
hasher = hashlib.sha256() |
|
|
|
hasher.update(body_bytes) |
|
|
|
computed_sha256 = base64.b64encode(hasher.digest()).decode('utf-8') |
|
|
|
logger.info(f" - Claim SHA256: {token_sha256}") |
|
|
|
logger.info(f" - Computed SHA256: {computed_sha256}") |
|
|
|
if hmac.compare_digest(token_sha256, computed_sha256): |
|
|
|
logger.info(" - JWT SHA256 signature verification successful!") |
|
|
|
return True |
|
|
|
else: |
|
|
|
logger.error(f"❌ [PlugNMeet Webhook] SHA256 mismatch! Token claim: {token_sha256}, Computed: {computed_sha256}") |
|
|
|
else: |
|
|
|
logger.error("❌ [PlugNMeet Webhook] JWT missing 'sha256' claim") |
|
|
|
else: |
|
|
|
logger.info(" - Hash-Token does not have 3 segments (not a JWT).") |
|
|
|
except jwt.PyJWTError as e: |
|
|
|
logger.warning(f"⚠️ [PlugNMeet Webhook] JWT decoding failed: {e}. Falling back to HMAC-SHA256 check.") |
|
|
|
logger.error(f"❌ [PlugNMeet Webhook] JWT decoding failed: {e.__class__.__name__}: {str(e)}") |
|
|
|
logger.warning(f"⚠️ [PlugNMeet Webhook] JWT decoding failed. Falling back to HMAC-SHA256 check.") |
|
|
|
|
|
|
|
# 2. Fallback: HMAC-SHA256 verification (for backward compatibility with test_webhook.py) |
|
|
|
expected_signature = hmac.new( |
|
|
|
@ -142,7 +170,9 @@ class PlugNMeetWebhookAPIView(APIView): |
|
|
|
hashlib.sha256 |
|
|
|
).hexdigest() |
|
|
|
|
|
|
|
logger.info(f" - Expected HMAC: {expected_signature}") |
|
|
|
if hmac.compare_digest(hash_token, expected_signature): |
|
|
|
logger.info(" - Fallback HMAC verification successful!") |
|
|
|
return True |
|
|
|
|
|
|
|
logger.error(f"❌ [PlugNMeet Webhook] Signature mismatch! \nReceived: {hash_token[:10]}...\nExpected HMAC: {expected_signature[:10]}...") |
|
|
|
|