coinbase api invalid signature error python on get request

Viewed 1800

trying to view my listed accounts in coinbase and I've generated my hmac hash and got no errors however for some reason I'm still getting {'message': 'invalid signature'} and a 401 error, I even tried to make a new key in coinbase to make sure that wasn't the issue

here is my code for reference I'm just starting out so I have very little to show, I'm trying to make a barebones version of the api documentation shown here https://docs.pro.coinbase.com/#signing-a-message

I have checked to make sure my api key is enabled and has proper access to the coinbase api, but honestly the documentation definitely could use some work as I've seen a lot of unanswered questions similar to this on stack and github and I think some things have been left out, I am also turning my signed hash to lowercase below as that was recommended in another post


def get_accounts(self):
        print("getting accounts")
        secret = bytes(self.secret, 'UTF-8')

        #unicode objects must be encoded before hashing?? what is that??
        timestamp = str(time.time())
        message = timestamp + 'GET' + self.baseurl + 'accounts' + ''
        message = bytes(message, 'UTF-8')
      
        hmac_key = base64.b64decode(secret)
        signature = hmac.new(hmac_key, message, hashlib.sha256)
        signature = signature.hexdigest()
        print('signature',signature)
     

        #final base 64 byte string to send, but we probably need a regular string
        signature_b64 = base64.b64encode(bytes(signature, 'UTF-8'))
        signature_b64 = signature_b64.decode("utf-8") 
        
        print('final',signature_b64.lower())

        headers = {
            'CB-ACCESS-SIGN': signature_b64.lower(),
            'CB-ACCESS-TIMESTAMP': timestamp,
            'CB-ACCESS-KEY': self.key,
            'CB-ACCESS-PASSPHRASE': self.passphrase,
            'Content-Type': 'application/json'
        }
       
        r = requests.get(self.baseurl + 'accounts', headers=headers)
        print (r.status_code)
        print( r.json())
2 Answers

This works for me:

timestamp = str(time.time())
message = timestamp + request.method + request.path_url
message = message.encode('utf-8')
if request.body:
    message = message + request.body
hmac_key = base64.b64decode(self.api_secret)
signature = hmac.new(hmac_key, message, hashlib.sha256)
signature_b64 = base64.b64encode(signature.digest()).decode('utf-8')

request.headers.update({
    'CB-ACCESS-SIGN': signature_b64,
    'CB-ACCESS-TIMESTAMP': timestamp,
    'CB-ACCESS-KEY': self.api_key,
    'CB-ACCESS-PASSPHRASE': self.api_pass,
    'Content-Type': 'application/json'
})

I struggled with this all afternoon, and found the coinbasepro python module to be the solution for me.

import coinbasepro
auth_client = coinbasepro.AuthenticatedClient(
    key=os.getenv(f'COINBASE_API_KEY'),
    secret=os.getenv(f'COINBASE_API_SECRET'),
    passphrase=os.getenv(f'COINBASE_API_PASSPHRASE')
)
accounts = auth_client.get_accounts()

It doesn't help that there are coinbase-commerce, coinbase[DEPRECATED], coinbase, and coinbasepro python modules all with different usage patterns.

Also, make sure you didn't switch the API KEY (shorter) and the API SECRET KEY (longer).

Related