""" The classes in this module contain the logic to authenticate an http request to the Mixpanel API """ import base64 import hashlib import json import time import six from mixpanel_query.utils import _tobytes, _totext, _unicode_urlencode from six.moves.urllib import request as url_request class SignatureAuth(object): """ Signature-based authentication uses your api secret to create and md5 hash of your request's parameters for verification by mixpanel This method is deprecated, but mixpanel currently has no plans to remove support for this method of authentication. Please see https://mixpanel.com/help/reference/data-export-api#authentication for more details. """ DEFAULT_EXPIRATION = 600 # expire requests after 10 minutes def __init__(self, client): self.client = client def _hash_args(self, args, secret=None): """ Hashes arguments by joining key=value pairs, appending the api_secret, and then taking the MD5 hex digest. """ for arg in args: if isinstance(args[arg], list): args[arg] = json.dumps(args[arg]) arg_strings = ["{}={}".format(arg, args[arg]) for arg in sorted(args.keys())] args_joined_string = ''.join(arg_strings) args_joined = _tobytes(args_joined_string) hash = hashlib.md5(args_joined) if secret: hash.update(_tobytes(secret)) elif self.client.api_secret: hash.update(_tobytes(self.client.api_secret)) return hash.hexdigest() def authenticate(self, url, params): """ returns a request object ready to be issued to the Mixpanel API """ params['api_key'] = self.client.api_key params['expire'] = int(time.time()) + self.DEFAULT_EXPIRATION # Creating signature if 'sig' in params: del params['sig'] params['sig'] = self._hash_args(params, self.client.api_secret) request_url = '{base_url}?{encoded_params}'.format( base_url=url, encoded_params=_unicode_urlencode(params) ) return url_request.Request(request_url) class SecretAuth(object): """ Secret-based authentication sends your api secret over https for verification by mixpanel. This method of authentication is the recommended authentication method. Please see https://mixpanel.com/help/reference/data-export-api#authentication for more details. """ def __init__(self, client): self.client = client def authenticate(self, url, params): """ returns a request object ready to be issued to the Mixpanel API """ request_url = '{base_url}?{encoded_params}'.format( base_url=url, encoded_params=_unicode_urlencode(params) ) request_headers = { 'Authorization': 'Basic ' + _totext(base64.standard_b64encode(_tobytes("{}:".format(self.client.api_secret)))) } return url_request.Request(request_url, headers=request_headers)