Browse Source

better jwt logging and validating for online class webhooks

master
Mohsen Taba 2 months ago
parent
commit
85f9b79f7d
  1. 34
      apps/course/views/webhook.py

34
apps/course/views/webhook.py

@ -115,25 +115,53 @@ class PlugNMeetWebhookAPIView(APIView):
return False return False
body_bytes = request.data 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) # 1. Try JWT verification (PlugNMeet production standard)
try: try:
# A JWT typically consists of three segments separated by dots # A JWT typically consists of three segments separated by dots
if len(hash_token.split('.')) == 3: 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') token_sha256 = decoded.get('sha256')
if token_sha256: if token_sha256:
hasher = hashlib.sha256() hasher = hashlib.sha256()
hasher.update(body_bytes) hasher.update(body_bytes)
computed_sha256 = base64.b64encode(hasher.digest()).decode('utf-8') 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): if hmac.compare_digest(token_sha256, computed_sha256):
logger.info(" - JWT SHA256 signature verification successful!")
return True return True
else: else:
logger.error(f"❌ [PlugNMeet Webhook] SHA256 mismatch! Token claim: {token_sha256}, Computed: {computed_sha256}") logger.error(f"❌ [PlugNMeet Webhook] SHA256 mismatch! Token claim: {token_sha256}, Computed: {computed_sha256}")
else: else:
logger.error("❌ [PlugNMeet Webhook] JWT missing 'sha256' claim") 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: 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) # 2. Fallback: HMAC-SHA256 verification (for backward compatibility with test_webhook.py)
expected_signature = hmac.new( expected_signature = hmac.new(
@ -142,7 +170,9 @@ class PlugNMeetWebhookAPIView(APIView):
hashlib.sha256 hashlib.sha256
).hexdigest() ).hexdigest()
logger.info(f" - Expected HMAC: {expected_signature}")
if hmac.compare_digest(hash_token, expected_signature): if hmac.compare_digest(hash_token, expected_signature):
logger.info(" - Fallback HMAC verification successful!")
return True return True
logger.error(f"❌ [PlugNMeet Webhook] Signature mismatch! \nReceived: {hash_token[:10]}...\nExpected HMAC: {expected_signature[:10]}...") logger.error(f"❌ [PlugNMeet Webhook] Signature mismatch! \nReceived: {hash_token[:10]}...\nExpected HMAC: {expected_signature[:10]}...")

Loading…
Cancel
Save