Last active
October 24, 2024 00:46
-
-
Save usmanm/93c323c333ed2a89a682a03b5d3e903e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import hashlib | |
| import hmac | |
| import json | |
| from urllib.parse import urlparse, urlunparse | |
| from django.http import HttpRequest | |
| def verify_signature(signing_key: str, request: HttpRequest, max_delay: int = 30) -> bool: | |
| """ | |
| Verify the signature of an incoming request using the provided signing key. | |
| Args: | |
| signing_key (str): The key used to sign the request from Operator. | |
| request (Request): The incoming request to be verified. | |
| Returns: | |
| bool: True if the signature is valid, False otherwise. | |
| """ | |
| headers = request.headers | |
| x_timestamp = headers.get("X-Timestamp") | |
| if not x_timestamp: | |
| return False | |
| # Is the request too old? | |
| now = time.time() | |
| if now - int(x_timestamp) > max_delay: | |
| return False | |
| x_signature = headers.get("X-Signature") | |
| if not x_signature: | |
| return False | |
| x_idempotency_key = headers.get("X-Idempotency-Key") | |
| if not x_idempotency_key: | |
| return False | |
| # Get the URL without query params. | |
| absolute_url = request.build_absolute_uri() | |
| parsed_url = urlparse(absolute_url) | |
| url_without_query = urlunparse(parsed_url._replace(query="")) | |
| # Determine the content based on the request method. | |
| if request.method == "GET": | |
| # Note that we sort the query params before encoding to ensure that the signature is | |
| # consistent. | |
| content = json.dumps(request.GET, sort_keys=True) | |
| elif request.method == "POST": | |
| content = request.body.decode("utf-8") | |
| else: | |
| return False | |
| # Construct the payload to verify. | |
| payload = f"{url_without_query}:{x_idempotency_key}:{x_timestamp}:{content}" | |
| expected_signature = hmac.new(signing_key.encode("utf-8"), payload.encode("utf-8"), hashlib.sha256).hexdigest() | |
| # Verify the signature. Using compare_digest is important for security, since it prevents | |
| # timing attacks. | |
| return hmac.compare_digest(x_signature, expected_signature) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment