john pfeiffer
  • Home
  • Categories
  • Tags
  • Archives

hmac signature rest client

# -*- coding: utf-8 -*-

import sys, time, hmac, hashlib, base64, urllib, urllib2, traceback, json

##############################################################
# STEP 0: CUSTOMIZE INPUT PARAMETERS
##############################################################

# REST API Gateway
API_GATEWAY = 'https://rest.example.com'

# API Key and Secret
API_KEY = 'example'
API_SECRET = 'examplesecret'


# User name and password
USER_ID = 'user'
PASSWORD = 'password'


##############################################################
# STEP 1: LOGIN (POST /rest/account/login)
##############################################################
def step_1_login():
    global session_id
    login_result = http_post('/rest/account/login', dict(id = USER_ID, password = PASSWORD))
    session_id = login_result['session']


##############################################################
# STEP 2: LIST SUBSCRIBED SPACES (GET /rest/spaces/list_spaces)
##############################################################
def step_2_list_spaces():
    list_spaces_result = http_post('/rest/spaces/list_spaces', None, session_id)
    print json.dumps(list_spaces_result, sort_keys = True, indent = 4, separators = (',', ': ')).decode('unicode-escape')


##############################################################
# UTILITY METHODS
##############################################################
def http_post(url, params = None, session_id = None):
    print 'POST', url
    headers = rest_api_header('POST', url, params, session_id)
    try:
        req = urllib2.Request(API_GATEWAY + url, data = urllib.urlencode(params or dict()), headers = headers)
        res = urllib2.urlopen(req)
        return rest_api_result(res.code, res.read())
    except urllib2.HTTPError as e:
        return rest_api_result(e.code, e.read())
    except urllib2.URLError as e:
        return rest_api_result(500, e.reason)


def rest_api_header(method, url, params, session_id):
    # Sign the REST API call with the current timestamp to ensure that it's secure and unique
    timestamp = str(int(time.time()))

    # Using the API secret, create a HMAC-SHA1 signature of the REST API call and its parameters and its timestamp
    unhashed = method + ' ' + url + ' '
    if params:
        sorted_params = ''
        for param_name in sorted(params.keys()):
            sorted_params += param_name.strip() + ' '
            param_value = params[param_name]
            if not param_value is None:
                if type(param_value) is unicode:
                    param_value = param_value.encode('utf-8')
                elif not isinstance(param_value, basestring):
                    param_value = str(param_value)
                sorted_params += param_value.strip()
            sorted_params += ' '
        unhashed += sorted_params.strip()
    unhashed += ' ' + timestamp
    if session_id:
        unhashed += ' ' + session_id
    hashed = hmac.new(API_SECRET, unhashed, hashlib.sha1)
    signature = base64.b64encode(hashed.digest())

    # Return the REST API call header
    return { 'X-Signature': signature, 'X-Timestamp': timestamp, 'X-App-Key': API_KEY, 'X-Session': session_id or '' }


def rest_api_result(status_code, response):
    # Success when status code is 200
    if status_code == 200:
        return json.loads(response) if response else dict()

    # Print error response and exit
    if status_code == 401 and response:
        response_json = json.loads(response)
        print '>> API ERROR encountered, error_code:', response_json['errorCode']
    else:
        print '>> UNEXPECTED ERROR encountered, reason:', response, traceback.format_exc()
    sys.exit(1)


if __name__ == '__main__':
    step_1_login()
    print session_id

  • « composeu
  • javascript functional twice »

Published

Oct 7, 2013

Category

python

~280 words

Tags

  • client 14
  • hmac 2
  • python 180
  • rest 3
  • signature 2