Home > database >  Nodejs Coinbase V2 REST endpoint returns invalid signature
Nodejs Coinbase V2 REST endpoint returns invalid signature

Time:11-28

Could not figure out why the coinbase v2 REST endpoint returns an invalid signature error, maybe someone see what I'm doing wrong. Everything I have found relates to the use of an old NPM package that is no longer maintained. There is still a Coinbase Pro package, but I don't want to communicate with the Pro API.

const { createHmac } = require('crypto');
const axios = require('axios');

(async () => {

  const cbApiKey = 'xxx';
  const apiSecret = 'xxx';
  const method = 'GET';
  const path = '/v2/user';
  const body = '';
 
  const timestamp = Math.floor(new Date().getTime() * 1e-3);
  const message = timestamp   method   path   body;

  const key = Buffer.from(apiSecret, 'base64');
  const cbAccessSign = createHmac('sha256', key).update(message).digest('base64');

  const instance = axios.create();

  try {
    const user = await instance.request({
      method,
      url: `https://api.coinbase.com${path}`,
      headers: {
        'CB-ACCESS-KEY': `${cbApiKey}`,
        'CB-ACCESS-SIGN': `${cbAccessSign}`,
        'CB-ACCESS-TIMESTAMP': `${timestamp}`,
        "Content-Type": 'application/json',
      },
    }); 
    console.log(user);
  } catch (error) {
    console.log(error);
  }  
})();

CodePudding user response:

I found the answer here https://github.com/coinbase/coinbase-node/blob/master/lib/ClientBase.js#L101

The correct code for the signature is

var signature = crypto.createHmac('sha256', this.apiSecret).update(message).digest('hex');

CodePudding user response:

I'm going to add something here because it was driving me crazy earlier, ie. trying crypto-js to no avail, then having to fight a good amount and put several workarounds in place to make 'crypto' as it's used in the tutorial work with all the impediments it currently enjoys.

Most of the invalid signatures as far as I can tell go back to the CB-ACCESS-SIGN and the biggest challenge was figuring out what a working equivalent in crypto-js looked like and getting all of this working properly in Angular 10.

A stripped-down version of the API call and the hash string creation for the access sign:

import * as CryptoJS from 'crypto-js';

async getUserCreds(apk: string, aps: string): Promise<any> {
  let access_sign = Access_Sign(getUnixTimestamp(), 'GET', '/v2/user','',aps)

  let httpOptions = {
    headers: new HttpHeaders({
      "CB-ACCESS-KEY": apk,
      "CB-ACCESS-SIGN": access_sign,
      "CB-ACCESS-TIMESTAMP": getUnixTimestamp().toString(),
      "Content-Type": "application/json"
    })
  }

  return this.http.get<any>('https://api.coinbase.com/v2/user',httpOptions)
    .pipe(shareReplay(), catchError((x) => { return this.handleErrorLog(x) 
    })).toPromise();
}


export function Access_Sign(timestamp: number, method: string, requestPath: string, body: string, secret: string) {

  let prehash = timestamp   method.toUpperCase()   requestPath   body;
  return CryptoJS.HmacSHA256(prehash, secret).toString(CryptoJS.enc.Hex);
}

export function getUnixTimestamp() {
  return Math.floor(Date.now() / 1000)
}
  • Related