12-17-2021 11:33
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

12-17-2021 11:33
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Guys, I'm developing a website function in Wordpress and using the PHP implementation of cURL to connect to the WebAPI. Despite spending hours on this, I still cannot get it to work... getting 401 Unauthorized error and Invalid Authorization errors depending on what changes I make to the code.
I can get the connection to work perfectly in Postman, and also in Powershell but for the life of me PHP scripting using same details just will not connect. It's doing my head in!!!
What am I missing here?
function FitBitTokensHandler( $atts ) {
// Setup parameters to obtain tokens from User Authorized Code passed from webpage callback using 'code'
$fitbituserauthcode = $_GET['code'];
$fitbitclientID = "12345";
$fitbitclientsecret = "abcdefghijklmnopqrstuvwxyz";
$fitbitauthorize = $fitbitclientID . ":" . $fitbitclientsecret;
$fitbitauthorize64 = base64_encode($fitbitauthorize);
// Exchange user auth code for access tokens
$url = "https://api.fitbit.com/oauth2/token";
$authcreds = "Basic " . $fitbitauthorize64;
$auth_header = array( "Authorization" => $authcreds , "Content-Type" => "application/x-www-form-urlencoded" );
$access_token_settings = array( "code" => $fitbituserauthcode, "grant_type" => "authorization_code", "client_id" => $fitbitclientID, "redirect_uri" => "https://website.com/fitbitauthresp" );
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $auth_header);
curl_setopt($curl, CURLOPT_POSTFIELDS, $access_token_settings);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_VERBOSE, true);
curl_setopt($curl, CURLOPT_STDERR, $out);
$result = curl_exec($curl);
curl_close($curl);
echo $curl;
}
add_shortcode( 'ProcessFitBitActivation', 'FitBitTokensHandler');
12-17-2021 11:35
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

12-17-2021 11:35
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
This is the output I'm getting from the cURL...
* Trying 104.16.66.50... * TCP_NODELAY set * Connected to api.fitbit.com (104.16.66.50) port 443 (#0) * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/certs/ca-certificates.crt CApath: /etc/ssl/certs * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN, server accepted to use http/1.1 * Server certificate: * subject: CN=*.fitbit.com * start date: Oct 28 10:52:09 2021 GMT * expire date: Jan 26 10:52:08 2022 GMT * subjectAltName: host "api.fitbit.com" matched cert's "*.fitbit.com" * issuer: C=US; O=Google Trust Services LLC; CN=GTS CA 1D4 * SSL certificate verify ok. > POST /oauth2/token HTTP/1.1 Host: api.fitbit.com Accept: */* Content-Length: 534 Content-Type: multipart/form-data; boundary=------------------------68a308f3229758b8 < HTTP/1.1 401 Unauthorized < Date: Fri, 17 Dec 2021 18:43:59 GMT < Content-Type: application/json;charset=utf-8 < Transfer-Encoding: chunked < Connection: keep-alive < Vary: Origin,Accept-Encoding < Cache-control: no-cache, private < Set-Cookie: JSESSIONID=972599784A994E89F7F3932589A2E0C3.fitbit1; Path=/; Secure; HttpOnly < WWW-Authenticate: Bearer realm="api.fitbit.com" < Set-Cookie: fct=1c5ec3e4a1e5420e8686541bd7d95bc2; Path=/; Secure; HttpOnly < Content-Language: en-GB < X-Frame-Options: SAMEORIGIN < Via: 1.1 google < CF-Cache-Status: DYNAMIC < Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" < Server: cloudflare < CF-RAY: 6bf24cd9d8cf75b1-LHR * HTTP error before end of send, stop sending < * Closing connection 0 Resource id #174

12-20-2021 11:59
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post



12-20-2021 11:59
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
At first glance, nothing is jumping out at me. If I'm reading your code correctly, it looks like you are building the endpoint correctly and don't have any typos. So, I'd like to offer a few suggestions to debug.
1. Are you able to view the completed endpoint definition that you built to make certain the data in the parameters is correct?
2. Are you able to get more information when the error is generated? We have a list of 401 Unauthorized error messages, See https://dev.fitbit.com/build/reference/web-api/troubleshooting-guide/error-messages/#401-unauthorize.... If you can get the error text returned, then it might be a clue to the cause of the error.
Senior Technical Solutions Consultant
Fitbit Partner Engineering & Web API Support | Google

12-20-2021 15:11
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

12-20-2021 15:11
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
curl command as I ended up changing the approach I used and this now works
as expected.
This script takes response from initial Fitbit User Authentication approval
and processes for tokens. Hope it helps someone else having similar
issues. 🐵
Cheers
// Setup initial parameters for connection to FitBit API
function FitBitConnectionHandler() {
$fitbituserauthcode = $_GET['code'];
$fitbitclientID = "12345";
$fitbitclientsecret = "a1b2c3d4e5f6g7abcdefghijklmnopqrstuvwxyz";
$fitbitauthorize = $fitbitclientID . ":" . $fitbitclientsecret;
$fitbitauthorize64 = base64_encode($fitbitauthorize);
$fitbitapiurl = 'https://api.fitbit.com/oauth2/token?code=';
$fitbitapigrant = '&grant_type=authorization_code';
$fitbitapiredir = '&redirect_uri=https://mywebsite.com/response_handler';
$fitbitapiheader = array();
$fitbitapiheader[] = 'Authorization: Basic ' . $fitbitauthorize64;
$fitbitapiheader[] = 'Content-type: application/x-www-form-urlencoded';
$fitbitapiheader[] = 'Content-Length: 0';
// Perform API connection using the setup parameters set above, exchanging
user code for API tokens
$fitbitapi = curl_init();
curl_setopt_array($fitbitapi, array(
CURLOPT_URL => $fitbitapiurl . $fitbituserauthcode . $fitbitapigrant .
$fitbitapiredir,
CURLOPT_HTTPHEADER => $fitbitapiheader,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_SSL_VERIFYPEER, false,
CURLOPT_VERBOSE => true,
CURLINFO_HEADER_OUT => true,
));
// Parse the returned API data for live tokens
$fitbitapiresponse = curl_exec($fitbitapi);
curl_close($fitbitapi);
$fitbitapitokens = json_decode($fitbitapiresponse,true);

