Module slack_sdk.signature
Slack request signature verifier
Expand source code
"""Slack request signature verifier"""
import hashlib
import hmac
from time import time
from typing import Dict, Optional, Union
class Clock:
def now(self) -> float: # skipcq: PYL-R0201
return time()
class SignatureVerifier:
def __init__(self, signing_secret: str, clock: Clock = Clock()):
"""Slack request signature verifier
Slack signs its requests using a secret that's unique to your app.
With the help of signing secrets, your app can more confidently verify
whether requests from us are authentic.
https://api.slack.com/authentication/verifying-requests-from-slack
"""
self.signing_secret = signing_secret
self.clock = clock
def is_valid_request(
self,
body: Union[str, bytes],
headers: Dict[str, str],
) -> bool:
"""Verifies if the given signature is valid"""
if headers is None:
return False
normalized_headers = {k.lower(): v for k, v in headers.items()}
return self.is_valid(
body=body,
timestamp=normalized_headers.get("x-slack-request-timestamp", None),
signature=normalized_headers.get("x-slack-signature", None),
)
def is_valid(
self,
body: Union[str, bytes],
timestamp: str,
signature: str,
) -> bool:
"""Verifies if the given signature is valid"""
if timestamp is None or signature is None:
return False
if abs(self.clock.now() - int(timestamp)) > 60 * 5:
return False
calculated_signature = self.generate_signature(timestamp=timestamp, body=body)
if calculated_signature is None:
return False
return hmac.compare_digest(calculated_signature, signature)
def generate_signature(self, *, timestamp: str, body: Union[str, bytes]) -> Optional[str]:
"""Generates a signature"""
if timestamp is None:
return None
if body is None:
body = ""
if isinstance(body, bytes):
body = body.decode("utf-8")
format_req = str.encode(f"v0:{timestamp}:{body}")
encoded_secret = str.encode(self.signing_secret)
request_hash = hmac.new(encoded_secret, format_req, hashlib.sha256).hexdigest()
calculated_signature = f"v0={request_hash}"
return calculated_signature
Classes
class Clock
-
Expand source code
class Clock: def now(self) -> float: # skipcq: PYL-R0201 return time()
Methods
def now(self) ‑> float
-
Expand source code
def now(self) -> float: # skipcq: PYL-R0201 return time()
class SignatureVerifier (signing_secret: str, clock: Clock = <slack_sdk.signature.Clock object>)
-
Slack request signature verifier
Slack signs its requests using a secret that's unique to your app. With the help of signing secrets, your app can more confidently verify whether requests from us are authentic. https://api.slack.com/authentication/verifying-requests-from-slack
Expand source code
class SignatureVerifier: def __init__(self, signing_secret: str, clock: Clock = Clock()): """Slack request signature verifier Slack signs its requests using a secret that's unique to your app. With the help of signing secrets, your app can more confidently verify whether requests from us are authentic. https://api.slack.com/authentication/verifying-requests-from-slack """ self.signing_secret = signing_secret self.clock = clock def is_valid_request( self, body: Union[str, bytes], headers: Dict[str, str], ) -> bool: """Verifies if the given signature is valid""" if headers is None: return False normalized_headers = {k.lower(): v for k, v in headers.items()} return self.is_valid( body=body, timestamp=normalized_headers.get("x-slack-request-timestamp", None), signature=normalized_headers.get("x-slack-signature", None), ) def is_valid( self, body: Union[str, bytes], timestamp: str, signature: str, ) -> bool: """Verifies if the given signature is valid""" if timestamp is None or signature is None: return False if abs(self.clock.now() - int(timestamp)) > 60 * 5: return False calculated_signature = self.generate_signature(timestamp=timestamp, body=body) if calculated_signature is None: return False return hmac.compare_digest(calculated_signature, signature) def generate_signature(self, *, timestamp: str, body: Union[str, bytes]) -> Optional[str]: """Generates a signature""" if timestamp is None: return None if body is None: body = "" if isinstance(body, bytes): body = body.decode("utf-8") format_req = str.encode(f"v0:{timestamp}:{body}") encoded_secret = str.encode(self.signing_secret) request_hash = hmac.new(encoded_secret, format_req, hashlib.sha256).hexdigest() calculated_signature = f"v0={request_hash}" return calculated_signature
Methods
def generate_signature(self, *, timestamp: str, body: Union[str, bytes]) ‑> Optional[str]
-
Generates a signature
Expand source code
def generate_signature(self, *, timestamp: str, body: Union[str, bytes]) -> Optional[str]: """Generates a signature""" if timestamp is None: return None if body is None: body = "" if isinstance(body, bytes): body = body.decode("utf-8") format_req = str.encode(f"v0:{timestamp}:{body}") encoded_secret = str.encode(self.signing_secret) request_hash = hmac.new(encoded_secret, format_req, hashlib.sha256).hexdigest() calculated_signature = f"v0={request_hash}" return calculated_signature
def is_valid(self, body: Union[str, bytes], timestamp: str, signature: str) ‑> bool
-
Verifies if the given signature is valid
Expand source code
def is_valid( self, body: Union[str, bytes], timestamp: str, signature: str, ) -> bool: """Verifies if the given signature is valid""" if timestamp is None or signature is None: return False if abs(self.clock.now() - int(timestamp)) > 60 * 5: return False calculated_signature = self.generate_signature(timestamp=timestamp, body=body) if calculated_signature is None: return False return hmac.compare_digest(calculated_signature, signature)
def is_valid_request(self, body: Union[str, bytes], headers: Dict[str, str]) ‑> bool
-
Verifies if the given signature is valid
Expand source code
def is_valid_request( self, body: Union[str, bytes], headers: Dict[str, str], ) -> bool: """Verifies if the given signature is valid""" if headers is None: return False normalized_headers = {k.lower(): v for k, v in headers.items()} return self.is_valid( body=body, timestamp=normalized_headers.get("x-slack-request-timestamp", None), signature=normalized_headers.get("x-slack-signature", None), )