I am using a PHP library (https://github.com/djchen/oauth2-fitbit) to retreive a users Fitbit data via Oauth2. I am getting the data correctly but I am not sure how to grab a specific item from the multidimensional array response.
I am using code below but doesnt work
$response = $provider->getResponse($request);
var_dump($response['encodedId'][0]);
Full PHP code
$provider = new djchen\OAuth2\Client\Provider\Fitbit([
'clientId' => 'xxx',
'clientSecret' => 'xxx',
'redirectUri' => 'http://xxx-env.us-east-1.elasticbeanstalk.com/a/fitbitapi'
]);
// start the session
session_start();
// If we don't have an authorization code then get one
if (!isset($_GET['code'])) {
// Fetch the authorization URL from the provider; this returns the
// urlAuthorize option and generates and applies any necessary parameters
// (e.g. state).
$authorizationUrl = $provider->getAuthorizationUrl();
// Get the state generated for you and store it to the session.
$_SESSION['oauth2state'] = $provider->getState();
// Redirect the user to the authorization URL.
header('Location: ' . $authorizationUrl);
exit;
// Check given state against previously stored one to mitigate CSRF attack
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
unset($_SESSION['oauth2state']);
exit('Invalid state');
} else {
try {
// Try to get an access token using the authorization code grant.
$accessToken = $provider->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
// We have an access token, which we may use in authenticated
// requests against the service provider's API.
echo $accessToken->getToken() . "\n";
echo $accessToken->getRefreshToken() . "\n";
echo $accessToken->getExpires() . "\n";
echo ($accessToken->hasExpired() ? 'expired' : 'not expired') . "\n";
// Using the access token, we may look up details about the
// resource owner.
$resourceOwner = $provider->getResourceOwner($accessToken);
var_export($resourceOwner->toArray());
// The provider provides a way to get an authenticated API request for
// the service, using the access token; it returns an object conforming
// to Psr\Http\Message\RequestInterface.
$request = $provider->getAuthenticatedRequest(
'GET',
'https://api.fitbit.com/1/user/-/profile.json',
$accessToken
);
// Make the authenticated API request and get the response.
$response = $provider->getResponse($request);
var_dump($response['encodedId'][0]);
Response data
eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0NjAzNzgxOTYsInNjb3BlcyI6InJ3ZWkgcnBybyByaHIgcmxvYyByc2xlIHJzZXQgcmFjdCByc29jIiwic3ViIjoiNEg4NU5WIiwiYXVkIjoiMjI3UUNXIiwiaXNzIjoiRml0Yml0IiwidHlwIjoiYWNjZXNzX3Rva2VuIiwiaWF0IjoxNDYwMzc0NTk2fQ.NN9OOx--3YLvwai0hl0ZRJ4MNWXlaMwcEJ_xxxxxb2382a930144c3a76e69567dcbf0d9834c574919fff8c268b378e635735f1bbf 1460378196 not expired array ( 'encodedId' => '4545NV', 'displayName'
=> 'dan', )...
I am using the same PHP library for FitBit API integration. The response you have pasted with the question is the data that is coming because of the following part of your code:
// requests against the service provider's API.
echo $accessToken->getToken() . "\n";
echo $accessToken->getRefreshToken() . "\n";
echo $accessToken->getExpires() . "\n";
echo ($accessToken->hasExpired() ? 'expired' : 'not expired') . "\n";
// Using the access token, we may look up details about the
// resource owner.
$resourceOwner = $provider->getResourceOwner($accessToken);
var_export($resourceOwner->toArray());
When you try to get the user profile from FitBit, you make the below request :
$request = $provider->getAuthenticatedRequest(
'GET',
'https://api.fitbit.com/1/user/-/profile.json',
$accessToken
);
// Make the authenticated API request and get the response.
$response = $provider->getResponse($request);
The $response comes in the below format and you can see there that "encodeId" is not the direct key there. Below is the example of var_dump($response); -
Array(
[user] => Array
(
[age] => 27
[avatar] => https://static0.fitbit.com/images/profile/defaultProfile_100_male.gif
[avatar150] => https://static0.fitbit.com/images/profile/defaultProfile_150_male.gif
[averageDailySteps] => 3165
[corporate] =>
[dateOfBirth] => 1991-04-02
[displayName] => Avtar
[distanceUnit] => METRIC
[encodedId] => 478ZBH
[features] => Array
(
[exerciseGoal] => 1
)
[foodsLocale] => en_GB
[fullName] => Avtar Gaur
[gender] => MALE
[glucoseUnit] => METRIC
[height] => 181
[heightUnit] => METRIC
[locale] => en_IN
[memberSince] => 2016-01-17
[offsetFromUTCMillis] => 19800000
[startDayOfWeek] => MONDAY
[strideLengthRunning] => 94.2
[strideLengthRunningType] => default
[strideLengthWalking] => 75.1
[strideLengthWalkingType] => default
[timezone] => Asia/Colombo
[topBadges] => Array
(
[0] => Array
(
)
[1] => Array
(
)
[2] => Array
(
)
)
[waterUnit] => METRIC
[waterUnitName] => ml
[weight] => 80
[weightUnit] => METRIC
)
)
In order to access anything in there you need to access it in this manner -
$encodedId = $response['user']['encodedId];
I hope this was helpful to you. You can ask more questions related to fitbit API as I have got it all working, including the Fitbit Subscriver API and Notifications.
Related
I am trying to use codebird to tweet using PHP. Initially I was unable to get Access Token but after I defined CallbackURL in settings that issue seems to be resolved. Now it is returning oauth token:
Codebird\Codebird Object ( [_oauth_token:protected] => codehere [_oauth_token_secret:protected] => codehere [_return_format:protected] => 0 [_supported_media_files:protected] => Array ( [0] => 1 [1] => 2 [2] => 3 ) [_version:protected] => 3.0.0-dev [_use_curl:protected] => 1 [_timeout:protected] => 10000 [_connectionTimeout:protected] => 3000 )
But when i try to tweet i get following error:
stdClass Object ( [errors] => Array ( [0] => stdClass Object ( [code]
=> 89 [message] => Invalid or expired token. ) ) [httpstatus] => 401 [rate] => )
Following is my code
Codebird\Codebird::setConsumerKey('copy+paste from twitter', 'copy+paste from twitter'); // I changed it to my settings
$cb = \Codebird\Codebird::getInstance();
if (! isset($_SESSION['oauth_token'])) {
// get the request token
$reply = $cb->oauth_requestToken(array(
'oauth_callback' => 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']
));
// store the token
$cb->setToken($reply->oauth_token, $reply->oauth_token_secret);
$_SESSION['oauth_token'] = $reply->oauth_token;
$_SESSION['oauth_token_secret'] = $reply->oauth_token_secret;
$_SESSION['oauth_verify'] = true;
// redirect to auth website
$auth_url = $cb->oauth_authorize();
header('Location: ' . $auth_url);
die();
} elseif (isset($_GET['oauth_verifier']) && isset($_SESSION['oauth_verify'])) {
// verify the token
$cb->setToken($_SESSION['oauth_token'], $_SESSION['oauth_token_secret']);
unset($_SESSION['oauth_verify']);
// get the access token
$reply = $cb->oauth_accessToken(array(
'oauth_verifier' => $_GET['oauth_verifier']
));
// store the token (which is different from the request token!)
$_SESSION['oauth_token'] = $reply->oauth_token;
$_SESSION['oauth_token_secret'] = $reply->oauth_token_secret;
// send to same URL, without oauth GET parameters
header('Location: ' . basename(__FILE__));
die();
}
// assign access token on each page load
$cb->setToken($_SESSION['oauth_token'], $_SESSION['oauth_token_secret']);
print_r($cb);
$params = array(
'status' => 'Auto Post on Twitter with PHP http://goo.gl/OZHaQD #php #twitter'
);
$reply = $cb->statuses_update($params);
print_r($reply);
Thanks in advance for the assistance.
Is your callback address the one registered with Twitter in the app definition?
Do you have "read and write" access in the app definition?
Have you exceeded the rate limit for posting?
I'd check those things first, as I don't see anything obviously missing from your code snippet.
I am trying to implement OAuth2 with Doctrine as an entity manager. I followed this tutorial exactly:
http://bshaffer.github.io/oauth2-server-php-docs/cookbook/doctrine2/
Here is my code that is called when a user makes a request to the API:
// obtaining the entity manager
$entityManager = EntityManager::create($conn, $config);
$clientStorage = $entityManager->getRepository('OAuthClient');
$clients = $clientStorage->findAll();
print_r($clients); // We are getting the clients from the database.
$userStorage = $entityManager->getRepository('OAuthUser');
$accessTokenStorage = $entityManager->getRepository('OAuthAccessToken');
$authorizationCodeStorage = $entityManager->getRepository('OAuthAuthorizationCode');
$refreshTokenStorage = $entityManager->getRepository('OAuthRefreshToken');
//Pass the doctrine storage objects to the OAuth2 server class
$server = new \OAuth2\Server([
'client_credentials' => $clientStorage,
'user_credentials' => $userStorage,
'access_token' => $accessTokenStorage,
'authorization_code' => $authorizationCodeStorage,
'refresh_token' => $refreshTokenStorage,
], [
'auth_code_lifetime' => 30,
'refresh_token_lifetime' => 30,
]);
$server->addGrantType(new OAuth2\GrantType\ClientCredentials($clientStorage));
// handle the request
$server->handleTokenRequest(OAuth2\Request::createFromGlobals())->send();
Whenever a call using the correct credentials is made, I get this response:
Array
(
[0] => OAuthClient Object
(
[id:OAuthClient:private] => 1
[client_identifier:OAuthClient:private] => testclient
[client_secret:OAuthClient:private] => testpass
[redirect_uri:OAuthClient:private] => http://fake.com
[hashOptions:protected] => Array
(
[cost] => 11
)
)
[1] => OAuthClient Object
(
[id:OAuthClient:private] => 2
[client_identifier:OAuthClient:private] => trevor
[client_secret:OAuthClient:private] => hutto
[redirect_uri:OAuthClient:private] => https://www.another.com
[hashOptions:protected] => Array
(
[cost] => 11
)
)
)
{"error":"invalid_client","error_description":"The client credentials are invalid"}
So we are getting the clients from the database, we should be checking them, and returning that they in fact exists and issuing an access token. However, for some reason, OAuth2 Server (can be seen here) can not match the given credentials with the stored credentials.
I do not think this is a Doctrine problem because I can retrieve the results fairly easily using findAll().
My question is:
Why is this happening, and how can I fix it?
I found the problem. In the tutorial (http://bshaffer.github.io/oauth2-server-php-docs/cookbook/doctrine2/) they fail to mention that when the client secret is checked with against a hashed version of the provided client secret.
In the tutorial they do not hash the example client secret when they put it in the database.
If you hash your client secret when inserting it into the database, it will work as expected.
The specific 401 error message I get is:
"error":"invalid_client","error_description":"The client credentials are invalid"}"
This error isn't listed anywhere in the PayPal documentation. I am certain I am using the test credentials and using the correct sandbox endpoint. The error occurs when I attempt to get an access token.
This is the class where the access token is retrieved:
private function _generateAccessToken($config) {
$base64ClientID = base64_encode($this->clientId . ":" . $this->clientSecret);
$headers = array(
"User-Agent" => PPUserAgent::getValue(RestHandler::$sdkName, RestHandler::$sdkVersion),
"Authorization" => "Basic " . $base64ClientID,
"Accept" => "*/*"
);
$httpConfiguration = $this->getOAuthHttpConfiguration($config);
$httpConfiguration->setHeaders($headers);
$connection = PPConnectionManager::getInstance()->getConnection($httpConfiguration, $config);
//print_r($connection); die;
$res = $connection->execute("grant_type=client_credentials");
$jsonResponse = json_decode($res, true);
if($jsonResponse == NULL ||
!isset($jsonResponse["access_token"]) || !isset($jsonResponse["expires_in"]) ) {
$this->accessToken = NULL;
$this->tokenExpiresIn = NULL;
$this->logger->warning("Could not generate new Access token. Invalid response from server: " . $jsonResponse);
} else {
$this->accessToken = $jsonResponse["access_token"];
$this->tokenExpiresIn = $jsonResponse["expires_in"];
}
$this->tokenCreateTime = time();
return $this->accessToken;
}
This is the $connection variable I have when I print_r (I removed the authorization string):
PayPal\Core\PPHttpConnection Object( [httpConfig:PayPal\Core\PPHttpConnection:private] => PayPal\Core\PPHttpConfig Object ( [headers:PayPal\Core\PPHttpConfig:private] => Array ( [User- Agent] => PayPalSDK/rest-sdk-php 0.6.0 (lang=PHP;v=5.4.21;bit=64;os=Linux_2.6.18- 308.16.1.el5;machine=x86_64;openssl=0.9.8e-fips-rhel5;curl=7.24.0) [Authorization] => Basic REMOVED AUTHORIZATION STRING == [Accept] => */* ) [curlOptions:PayPal\Core\PPHttpConfig:private] => Array ( [32] => 3 [78] => 30 [19913] => 1 [13] => 60 [10018] => PayPal-PHP-SDK [10023] => Array ( ) [81] => 2 [64] => 1 ) [url:PayPal\Core\PPHttpConfig:private] => https://api.sandbox.paypal.com/v1/oauth2/token [method:PayPal\Core\PPHttpConfig:private] => POST [retryCount:PayPal\Core\PPHttpConfig:private] => 1 ) [logger:PayPal\Core\PPHttpConnection:private] => PayPal\Core\PPLoggingManager Object ( [loggerName:PayPal\Core\PPLoggingManager:private] => PayPal\Core\PPHttpConnection [isLoggingEnabled:PayPal\Core\PPLoggingManager:private] => 1 [loggingLevel:PayPal\Core\PPLoggingManager:private] => 3 [loggerFile:PayPal\Core\PPLoggingManager:private] => PayPal.log ))
As far I can tell, I have correct credentials, correct endpoint, not sure what else it could be?
A HTTP401 on /token is returned if the client_id/secret aren’t recognized (either the wrong credentials for the environment, or the credentials aren’t active).
Can you run a test via cURL to rule out any environment / code-specific issues?
curl -v -u "client_id:secret" "https://api.sandbox.paypal.com/v1/oauth2/token" -X POST -d "response_type=token&grant_type=client_credentials"
(Replace client_id and secret above with your own)
Make sure payment $config mode is Sandbox and clientId and clientSecret keys are Sandbox same time.
I am using the Google Api PHP client to Log the user in. I want to get the Users Email address. I have the following code.
Scope:
$client->setScopes('https://www.googleapis.com/auth/userinfo.profile');
Code:
$request = new apiHttpRequest("https://www.googleapis.com/oauth2/v2/userinfo?alt=json");
$userinfo = $client->getIo()->authenticatedRequest($request);
$response = $userinfo->getResponseBody();
print "<pre>" . print_r(json_decode($response, true), true) . "</pre>";
This give me only the following details
Array
(
[id] => 110084312800396764
[name] => Harsha M V
[given_name] => Harsha M
[family_name] => V
[picture] => https://lh6.googleusercontent.com/-Xusc8lwgLIQ/AAAAAAAAAAI/AAAAAAAAAAA/sOthy23uJGk/photo.jpg
[locale] => en
)
Setting the scope in an array does the job.
$this->client->setScopes(array('https://www.googleapis.com/auth/analytics.readonly', 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile'));
https://www.google.com/accounts/AuthSubRequest?next=http://www.example.com/index.php&scope=https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/analytics.readonly&secure=0&session=1
or
https://www.google.com/accounts/AuthSubRequest?next=http://www.example.com/index.php&scope=email+https://www.googleapis.com/auth/analytics.readonly&secure=0&session=1
both of above links works for me in php
I am working on an application that is basically going to operate in a Kiosk, the point is to allow users while they are at a business to be able to login to facebook and after logging in it posts a message saying they are there, afterwords they are given a coupon.
The problem has arisen that after they have logged in and then logged out, the next person logs in with their account ends up posting as the previous user, this continues adnauseum.
After getting their coupon the script automatically logs them out after 15 seconds and returns the application to the home screen for the next user. When they login, which they are able to do it returns them to the page asking for permission to post, but it is pulling all of the previous users information. This is the code being called in the page after being sent to logging in on facebook.
<?php
//include the Facebook PHP SDK
include_once 'couponGenerator/facebook.php';
//start the session if necessary
if( session_id() ) {
} else {
session_start();
}
//instantiate the Facebook library with the APP ID and APP SECRET
$facebook = new Facebook(array(
'appId' => '00000000000',
'secret' => '000000000000000000000',
'cookie' => true,
'status' => true,
'oath' => true
));
$access_token = $facebook->getAccessToken();
$_SESSION['active'][$access_token];
//get the news feed of the active page using the page's access token
$page_feed = $facebook->api(
'/me/feed',
'GET',
array(
'access_token' => $_SESSION['active']['access_token']
)
);
$fbuser = $facebook->api('/me');
//var_dump($page_feed); exit;
?>
I have attempted on the homepage of of deleting facebook cookies and sessions and this has not solved anything, I am just trying to figure out what I am doing wrong and any advice would be very welcome.
$facebook->destroySession();
$facebook->_killFacebookCookies();
public function _killFacebookCookies()
{
// get your api key
$apiKey = $this->getAppId();
// get name of the cookie
$cookie = $this->getSignedRequestCookieName();
$cookies = array('user', 'session_key', 'expires', 'ss');
foreach ($cookies as $name)
{
setcookie($apiKey . '_' . $name, false, time() - 3600);
unset($_COOKIE[$apiKey . '_' . $name]);
}
setcookie($apiKey, false, time() - 3600);
unset($_COOKIE[$apiKey]);
$this->clearAllPersistentData();
}
Here is the updated connection class
`
<?php
//include the Facebook PHP SDK
include_once 'facebook.php';
//instantiate the Facebook library with the APP ID and APP SECRET
$facebook = new Facebook(array(
'appId' => '122628977190080',
'secret' => '123123123123123123123123',
'cookie' => true
));
$access_token = $facebook->getAccessToken();
unset ($_SESSION['active'][$access_token]);
session_unregister ($_SESSION['active'][$access_token]);
//Get the FB UID of the currently logged in user
$user = $facebook->getUser();
//if the user has already allowed the application, you'll be able to get his/her FB UID
if($user) {
//start the session if needed
if( session_id() ) {
} else {
session_start();
}
//do stuff when already logged in
//get the user's access token
$access_token = $facebook->getAccessToken();
//check permissions list
$permissions_list = $facebook->api(
'/me/permissions',
'GET',
array(
'access_token' => $access_token
)
);
//check if the permissions we need have been allowed by the user
//if not then redirect them again to facebook's permissions page
$permissions_needed = array('publish_stream', 'email');
foreach($permissions_needed as $perm) {
if( !isset($permissions_list['data'][0][$perm]) || $permissions_list['data'][0][$perm] != 1 ) {
$login_url_params = array(
'scope' => 'publish_stream,email',
'fbconnect' => 1,
'display' => "page",
'next' => 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']
);
$login_url = $facebook->getLoginUrl($login_url_params);
header("Location: {$login_url}");
exit();
}
}
//if the user has allowed all the permissions we need,
//get the information about the pages that he or she managers
$accounts = $facebook->api(
'/me/accounts',
'GET',
array(
'access_token' => $access_token
)
);
//save the information inside the session
$_SESSION['access_token'] = $access_token;
$_SESSION['accounts'] = $accounts['data'];
//save the first page as the default active page
$_SESSION['active'] = $accounts['data'][0];
//redirect to manage.php
header('Location: ../facebook_result.php');
} else {
//if not, let's redirect to the ALLOW page so we can get access
//Create a login URL using the Facebook library's getLoginUrl() method
$login_url_params = array(
'scope' => 'read_stream,email',
'fbconnect' => 1,
'display' => "page",
'next' => 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']
);
$login_url = $facebook->getLoginUrl($login_url_params);
//redirect to the login URL on facebook
header("Location: {$login_url}");
exit();
}
?>`
After calling the logoff script, I am run this piece of code on the homepage to see if everything is set.
<?php
try {
$uid = $facebook->getUser();
$fbme = $facebook->api('/me');
echo "$uid";
} catch (FacebookApiException $e) {
print_r($e);
}
?>
it gives me this result
FacebookApiException Object ( [result:protected] =>
Array ( [error] => Array ( [message] =>
An active access token must be used to query information about the current user.
[type] => OAuthException [code] => 2500 ) )
[message:protected] => An active access token must be
used to query information about the current user.
[string:private] => [code:protected] => 0 [file:protected] =>
/home/m3dev/public_html/couponsite/couponGenerator/base_facebook.php
[line:protected] => 1046 [trace:private] => Array ( [0] => Array ( [file] => /home/m3dev/public_html/couponsite/couponGenerator/base_facebook.php [line] => 751 [function] => throwAPIException [class] => BaseFacebook [type] => -> [args] => Array ( [0] => Array ( [error] => Array ( [message] => An active access token must be used to query information about the current user. [type] => OAuthException [code] => 2500 ) ) ) ) [1] => Array ( [function] => _graph [class] => BaseFacebook [type] => -> [args] => Array ( [0] => /me ) ) [2] => Array ( [file] => /home/m3dev/public_html/couponsite/couponGenerator/base_facebook.php [line] => 560 [function] => call_user_func_array [args] => Array ( [0] => Array ( [0] => Facebook Object ( [appId:protected] => 162628977190080 [apiSecret:protected] => **SECRET KEY REMOVED ** [user:protected] => 0 [signedRequest:protected] => Array ( [algorithm] => HMAC-SHA256 [code] => 961628b1ca0354544541d58e.1-34319949|p3D3pSNoawlC1wBllhiN7zoEpJY [issued_at] => 1331218933 [user_id] => 34319949 ) [state:protected] => [accessToken:protected] => 162628977190080|**SECRET KEY REMOVED** [fileUploadSupport:protected] => ) [1] => _graph ) [1] => Array ( [0] => /me ) ) ) [3] => Array ( [file] => /home/m3dev/public_html/couponsite/index.php [line] => 71 [function] => api [class] => BaseFacebook [type] => -> [args] => Array ( [0] => /me ) ) ) )
You may be destroying a Facebook session but you don't seem to be destroying your own session.
Clear out
$_SESSION['active'][$access_token];
You need to force Facebook Re-Authentication for each user.
I'm not sure if the PHP API you're using supports this, but the OAuth dialog can receive a auth_type that when valued to reauthenticate forces the user to provide his credentials:
$dialog_url = "https://www.facebook.com/dialog/oauth?client_id="
. $app_id . "&redirect_uri=" . urlencode($my_url)
. '&auth_type=reauthenticate&auth_nonce=' . $auth_nonce;
This can be done useg the Javascript API as well.