Cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

401 Unauthorized Error Using PHP cURL when trying to obtain tokens.

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');

 

Best Answer
0 Votes
3 REPLIES 3

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

Best Answer
0 Votes

Hi @CrannogDigital 

 

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.   

 

 

Gordon Crenshaw
Senior Technical Solutions Consultant
Fitbit Partner Engineering & Web API Support | Google
Best Answer
0 Votes
Hi, seems to be something buggy in the way header info was being passed via
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);
Best Answer
0 Votes