Coinbase API (PHP): Invalid signature

I can not get the Coinbase base API to work because of this error:

{"errors":[{"id":"authentication_error","message":"invalid signature"}]}

I checked multiple times the code, and everything looks correct in relation to the official docs at API Key Authentication, still, I get the error, this is the code:

 $ch = curl_init('https://api.coinbase.com/v2/user');
 $request_path =  '/v2/user';
 $body = '';
 $time = json_decode(file_get_contents('https://api.coinbase.com/v2/time'), true)['data']['epoch'];
 $signature = $time . 'GET' . $request_path . json_encode($body);
 $signature = hash_hmac('sha256', $signature, 'xxxxxxx');
 $headers = ['Content-Type: application/json',
                     'CB-ACCESS-KEY: xxxxx',
                     'CB-ACCESS-SIGN: ' . $signature,
                     'CB-ACCESS-TIMESTAMP:' . $time,
                     'CB-VERSION: 2017-05-24',
                ];
 curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
 echo curl_exec($ch);

Hello @schiocco. Welcome to the forum! For the details regarding your concern, we will check on this for you with our team. We will get back to you once we have more information. Keep in touch!

3 Likes

Great thanks because it looks like a bug on Coinbase, I asked also on https://stackoverflow.com/

I want to mention that this issue is blocking us from adding Coinbase as the leading provider for our software Boxcoin (https://boxcoin.dev/). We successfully implemented Gemini for now (it worked immediately and with the same key authentication logic).

Boxcoin was released a few months ago and already has hundreds of sales.

Anyone here???

Mind that the issue happens also without json_encode($body). I tried multiple combinations, multiple apis, POST and GET, nothing works.

I’m shocked that after 10 days no one solve this bug on the official API. And no one replies.
A multi-billion dollar company unable to provide a basic support level.

I will continue to post here multiple times till I get an answer.
And all of this without taking in consideration that this seem a Coinbase bug with is even more shocking.

Regards

@schiocco we appreciate your passion for the space and the desire to use our products. While we have a team monitoring the forum, we are hoping to get other contributors to participate as well. It is a process.

A few questions for you in hopes of finding a resolution:

  1. Have you tried /api/v2/user as request path?

  2. Are you using the /v2/time endpoint for the time generate, other than using the standard epoch time in seconds?

We see you’re using the time endpoint to generate the timestamp. For the timestamp, have you tried to remove the json_decode, and replace it with Math.floor(Date.now() / 1000); instead?

  1. Lastly, have you tried to convert the HMAC to decimal string when generating the signature?

This is legacy code and we are working with the right teams to ensure it gets updated. That said, your negativity won’t help in getting issues resolved. Persistent and firm kindness is your best bet as we hope to build this community over time :wink:

Thanks again for being here.

3 Likes

Hi, most of your suggestions are unfortunately wrong:

  1. I assume the URL you suggested “https://api.coinbase.com/api/v2/user” is wrong. I’m using “https://coinbase.com/api/v2/user

  2. I don’t know what you mean, anyway I think yes because the URL is “https://api.coinbase.com/v2/time”, but I don’t understand why you are asking it if you have the code, just confused.

  3. The code you posted “Math.floor(Date.now() / 1000);” is a JS code. I’m using PHP, anyway I already tried with it using the PHP “time()” function.

  4. I don’t know what you mean for “convert the HMAC to decimal string”, are you referring to hexadecimal? Anyway the PHP function I posted already does it.

Anyway I tried some changes, I always get “invalid signature”, this is a bug of Coinbase (and yes, this quite is shocking).

Here some variant I tried:

1

   $ch = curl_init('https://coinbase.com/api/v2/user');
    $request_path =  '/api/v2/user';
    $body = '';
    $time = json_decode(file_get_contents('https://api.coinbase.com/v2/time'), true)['data']['epoch'];
    $signature = $time . 'GET' . $request_path . $body;
    $signature = hash_hmac('SHA256', $signature, 'xxx');
    $headers = ['Content-Type: application/json',
                     'CB-ACCESS-KEY: xxx',
                     'CB-ACCESS-SIGN: ' . $signature,
                     'CB-ACCESS-TIMESTAMP: ' . $time,
                     'CB-VERSION: 2017-05-24',
                     'User-Agent: request'
                ];
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    echo curl_exec($ch);

2

 $ch = curl_init('https://coinbase.com/api/v2/user');
    $request_path =  '/api/v2/user';
    $body = '';
    $time = time();
    $signature = $time . 'GET' . $request_path . $body;
    $signature = hash_hmac('SHA256', $signature, 'xxx');
    $headers = ['Content-Type: application/json',
                     'CB-ACCESS-KEY: xxx',
                     'CB-ACCESS-SIGN: ' . $signature,
                     'CB-ACCESS-TIMESTAMP: ' . $time,
                     'CB-VERSION: 2017-05-24',
                     'User-Agent: request'
                ];
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    echo curl_exec($ch);

Thank you very much for the reply!

And thank you as well @schiocco - we will keep working to figure this out (and keep updating you).

Great! Thank you! I will lwait

@schiocco we did some additional testing and think this should work:

 $ch = curl_init('https://api.coinbase.com/v2/user');
    $request_path =  '/v2/user';
    $body = '';
    $key= "<api_key>";
    $s = "<secret>";
    $time = time();
    $signature = $time . 'GET' . $request_path . $body;
    $signature = hash_hmac('SHA256' , $signature, $s);
    $headers = ['Content-Type: application/json',
                     'CB-ACCESS-KEY: '. $key,
                     'CB-ACCESS-SIGN: ' . $signature,
                     'CB-ACCESS-TIMESTAMP: ' . $time,
                     'CB-VERSION: 2017-05-24',
                ];
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // important
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);  // important
    echo curl_exec($ch);

we believe this is an issue with the curl

{"data":{"id":"xxx","name":"Antony Wang","username":null,"profile_location":null,"profile_bio":null,"profile_url":null,"avatar_url":"xxxxxxx","resource":"user","resource_path":"/v2/user","legacy_id":"61bab32ba0f7e60fd68e7c71","time_zone":"Pacific Time (US \u0026 Canada)","native_currency":"USD"..."user_type":"individual"}}

Unfortunately, your code is not working for me. I get the same invalid signature error. I tried with time() and the coinbase time, I tried on 2 servers (localhost and a live server) and same error, so the issue is not my cURL but with Coinbase. Maybe my key is not correct? Here it is:


The code

2022-09-15_093634

@schiocco - thank you for continuing to try - ive passed this along to see if the key needs a second look…

1 Like

Nothing? Really? Incredible.

@schiocco - Your passive aggressive approach here wont help. The company just closed Q3 and has this week off for recharge. The team assisting with the errors you are seeing will be back on line next week.

In the meantime - please feel free to send a ticket in here - https://help.coinbase.com/en/contact-us?

1 Like