Coinbase Pro API Authentication

@jacobH - let us know if this helps! as always - thanks @cleggink !!

1 Like

@Nick_of_Time - hunch is that something is wrong with the signature

signature.Write( byte (prehashString))
cbAccessSignature := base64.URLEncoding.EncodeToString(signature.Sum(nil))

Will you please check and advise?

@larry.kubin I am having trouble integrating coinbase connect with my web app.

Im following the steps linked here Integrating Coinbase Connect with your web application - Coinbase Developers however keep getting HTTP/1.1 401 Unauthorized response when requesting an auth token. Im following the procedure to a T any ideas what might be going wrong?

@bborg - Alex here, happy to look into this for you. Thank you for bringing this up and ill follow up asap with any insights/remedies i can provide. Thanks and welcome!

@bborg - we have new documentation for this - Welcome - Will you please take a look and let me know if this helps?

Hi Alex yes it helped greatly. However I was wondering whether there was a way to use Oauth2 authentication with the Sandbox so that I can add fake funds to the account for testing purposes. Or is there another way to get test accounts?

At this time - Oauth2 is only for retail and wont work with exchange/pro - something we’re noting and seeing where opportunities for more testing can be surfaced. Thanks @bborg !

Authenticate Coinbase Pro API

  • Managing API keys is not currently supported on the Coinbase Pro mobile app. Select the API link from the menu .
  • Under Profile Information, select the API Settings tab, then select + New API Key.Select your profile and appropriate permissions, create a passphrase, and then enter in your 2-Factor Authentication code.

Regards,
Rachel Gomez

I got this python code to create a working signature:

key = base64.b64decode(secret)
msg = message.encode(‘utf-8’)
ash = hmac.digest(key, msg, hashlib.sha256)
sig = base64.b64encode(ash).decode(‘utf-8’)

But when I tried it with javascript and AHK, creating the same signature, {“message”:“invalid signature”} gets returned.

Any ideas why that might be. Is there some difference in the signature string?

I haven’t found that the ‘Accept’ line is required for authentication.
And the secret is used as the key.
Maybe check your signature against one made by python.

Here’s a CryptoJS snippet that works:

var key = CryptoJS.enc.Base64.parse(secret);
var hash = CryptoJS.HmacSHA256(message, key);
var signature = hash.toString(CryptoJS.enc.Base64);

Answering my own question above, in case it’s of any help to others:

I found out that an AHK script I had made was rejected as having an invalid signature, even though the correct signature was generated. It was rejected because I didn’t send the variable body in the send command, along with the headers having the signature, passphrase, etc.

Hey all, new here and got pretty excited about using the api.
I’m using node js and was able to try @larry.kubin test code.
Everything works fine on the GET request and I can see the filled orders.
I’d like to also be able to POST requests which I’m having a bit of difficulty trying to figure out.
Also, it is a bit confusing that I can’t find any working samples for the Coinbase Pro api.
I tried using larry’s code by switching the GET to Post and creating a body for the transaction, but I’m getting a

statusCode: 401
{"message":"invalid signature"}

I’d like to be able to post buy orders at a specific set price as well as market price.
Any help and pointers in the right direction are greatly appreciated.

thank you!

This and other threads have info on making a valid signature.

Ok, tried it with cryptojs as well and same thing.
This is what I have so far:

const config = require('dotenv').config();
var CryptoJS = require("crypto-js");
const https = require('https');

var cb_access_timestamp = Date.now() / 1000;
var cb_access_passphrase = process.env.cb_access_passphrase;
var cb_api_key = process.env.cb_api_key;
var cb_secret = process.env.cb_secret;

var path = '/orders';
var body = JSON.stringify({
    price: '45415.51',
    size: '0.0001',
    side: 'buy',
    product_id: 'BTC-USD'
});
var method = 'POST';

var message = cb_access_timestamp + method + path + body;

var key = CryptoJS.enc.Base64.parse(cb_secret);
var hash = CryptoJS.HmacSHA256(message, key);
var sign = hash.toString(CryptoJS.enc.Base64);

const options = {
  hostname: 'api.exchange.coinbase.com',
  port: 443,
  path: path,
  method: method,
  headers: {
    'Content-Type': 'application/json',
    'Content-Length': 0,
    'User-Agent': 'MyTradingBot',
    'CB-ACCESS-KEY': cb_api_key,
    'CB-ACCESS-PASSPHRASE': cb_access_passphrase,
    'CB-ACCESS-SIGN': sign,
    'CB-ACCESS-TIMESTAMP': cb_access_timestamp
  }
}

const req = https.request(options, res => {
  console.log(`statusCode: ${res.statusCode}`)

  res.on('data', d => {
    process.stdout.write(d)
  })
})

req.on('error', error => {
  console.error(error)
})

req.end()

Still getting:

statusCode: 401
{"message":"invalid signature"}

I can see you’re missing type:limit. Maybe you need strings like this:

'product_id': 'BTC-USD',
'type': 'limit',
'side': 'buy',
'price': '25000',
'size': '0.00001'

added that… no difference :frowning:

Maybe s.o. who knows JS can help. What does your message string look like?

In case it is helpful, I have had success with the Python code below (or as a Github Gist) which is a slight tweak to @SubStandard’s code above, mainly adding the passphrase (I’m not sure if the other changes were important but this works for me).

import time
import hmac
import hashlib
import requests
import base64


class CoinbaseAuth(requests.auth.AuthBase):
	def __init__(self, api_key, secret_key, api_passphrase):
		self.api_key = api_key
		self.api_passphrase = api_passphrase
		self.secret_key = base64.b64decode(secret_key)
	
	def __call__(self, request):
		timestamp = str(time.time())
		message = timestamp + request.method + request.path_url + (request.body or '')
		signature = base64.b64encode(hmac.new(self.secret_key, message.encode(), hashlib.sha256).digest())
		request.headers.update({
			'CB-ACCESS-SIGN': signature,
			'CB-ACCESS-TIMESTAMP': timestamp,
			'CB-ACCESS-KEY': self.api_key,
			'CB-ACCESS-PASSPHRASE': self.api_passphrase
		})
		return request


COINBASE_API = 'https://api.exchange.coinbase.com'

API_KEY = 'xxx'
API_SECRET = 'xxx'
API_PASSPHRASE = 'xxx'

auth = CoinbaseAuth(API_KEY, API_SECRET, API_PASSPHRASE)

r = requests.get(COINBASE_API + '/oracle', auth=auth)
print(r.json())
1 Like

@cleggink I think I had a couple things incorrect. Most notably, my prehashString included path instead of body. I got it working and wrote a synopsis: Coinbase Cloud with GoLang

@arood I was able to get it working. I made a couple errors building the “Signing Message”. I wrote an article: Coinbase Cloud with GoLang. Hopefully, this will help others avoid some of the mistakes I made. (Github link → jhennin/coinbase-cloud-go)

1 Like