Source code for canvas_data.hmac_auth

import base64
import hashlib
import hmac
import logging
import sys
from datetime import datetime

import requests

try:
    from urllib import urlencode
except:
    # For Python 3
    from urllib.parse import urlencode

try:
    from urlparse import parse_qs
except:
    # For Python 3
    from urllib.parse import parse_qs

logger = logging.getLogger(__name__)

API_ROOT = 'https://api.inshosteddata.com'
SIGNATURE_MESSAGE_TEMPLATE = '''GET
api.inshosteddata.com


{resource_path}
{args}
{date}
{api_secret}'''


[docs]class CanvasDataHMACAuth(requests.auth.AuthBase): """Attaches HMAC Authentication to the given Request object.""" def __init__(self, api_key, api_secret, api_root=API_ROOT): self.api_key = api_key self.api_secret = api_secret self.api_root = api_root self.req_date = datetime.utcnow().strftime('%a, %d %b %y %H:%M:%S GMT') def __call__(self, r): # build the auth header path = r.url logger.debug(r.headers) if path.startswith(self.api_root): path = path[len(self.api_root):] # if the URL has a query string, remove it and sort the key-value pairs args_str = '' if '?' in path: [path, qs] = path.split('?') logger.debug('%s %s', path, qs) kv_pairs = qs.split('&') kv_pairs.sort() args_str = '&'.join(kv_pairs) sig_body = SIGNATURE_MESSAGE_TEMPLATE.format( resource_path=path, api_secret=self.api_secret, args=args_str, date=self.req_date, ) if sys.version_info >= (3, 0): sig_body = bytes(sig_body, 'utf-8') sig_api_secret = bytes(self.api_secret, 'utf-8') else: sig_body = str(sig_body) sig_api_secret = str(self.api_secret) sig_hmac = hmac.new( sig_api_secret, msg=sig_body, digestmod=hashlib.sha256 ) sig_digest = sig_hmac.digest() signature = base64.b64encode(sig_digest) if sys.version_info >= (3, 0): signature = signature.decode('utf-8') r.headers['Authorization'] = 'HMACAuth {0}:{1}'.format(self.api_key, signature) r.headers['Date'] = self.req_date return r