Hey everyone,
I am trying to get the session_key and secret for a facebook session (offline_access) in canvas application.
However, I am unable to get these two particular variables.
When, I am testing the same code locally, I can get the variables above (but this can be because the local app is not a canvas application)
I 'm using the following code, for redirect:
$facebook->getLoginUrl(array(
'canvas' => 1,
'fbconnect' => 0,
'req_perms' => 'user_status,publish_stream,offline_access'
));
Can someone suggest me on how I can grab the session_key and secret, when the user authorizes the application? (for permanent offline access)
Here is an example session dump via Facebook:
Array (
[uid] => 100000926583671
[session_key] =>
[expires] => 0
[secret] =>
[base_domain] =>
[access_token] => 183043495039366|3ab6ac2asdkhj1bcfdec13d7-100000926583671|jJQaIT-n80YxioAasdwN0cm99U
[sig] => 2f64sadasc1da31c12927a052752776
)
and this is the error:
Array (
[error] => Array (
[type] => OAuthException
[message] => An active access token must be used to query information about the current user.
)
)
session_key and secret are now deprecated, and Facebook wants you to use Oauth authentication schema. Then, you will have to use given access_token (that you correctly get in $session) to make your api calls.
Try:
$session = $facebook->getSession();
$me = $facebook->api('/100000926583671',
array('access_token' => $session['access_token'])
);
var_dump($me);
Ref:
http://developers.facebook.com/docs/authentication/
Related
I'm developing a PHP that reads the emails from gmail using the Gmail API.
Basically I'm doing exactly as the quickstart page does (https://developers.google.com/gmail/api/quickstart/php).
So firstly I load the client:
require __DIR__ . '/Google/vendor/autoload.php';
$client = new Google_Client();
$client->setAuthConfigFile(__DIR__ . '/client_secret.json');
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$client->setScopes(Google_Service_Gmail::MAIL_GOOGLE_COM);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/index.php');
Then if I load the credentials from the db stored using an user id from my app.
If the credentials ar not present I do the redirect as the documentation sais:
$client->setAccessType('offline');
$client->setApprovalPrompt('force');
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
After the authorization I get the access token using the code provided by google on my redirect url:
$token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
//storing the data in the db
header('Location: /index.php');
Of course if the token expires I do the refresh during the authentication process:
if($client->isAccessTokenExpired()) {
$refreshToken = $client->getRefreshToken();
$client->fetchAccessTokenWithRefreshToken($refreshToken);
$newToken = $client->getAccessToken();
$newToken['refresh_token'] = $refreshToken;
//store the new token
}
So after this I can access the email list of my user, and it works perfectly.
The problem is that if I log in with my account, I see the correct email, but after loggin in with another account with another user I see the same emails form both accounts.
So for example if I authorize for the user 1 the account smith#gmail.com, then for the user 2 the email seth#gmail.com, in both cases I will see the same emails (from smith#gmail.com).
I have checked if the problem is mine, so if the access token loaded are the same, but is not like that unfortunately, the access tokens are different.
The other crazy thing is that if I refresh a token for the second account (smith#gmail.com), I will see the correct emails, but now seth, will see the smith emails.
What is going on? what I miss?
UPDATE:
I've tried every step and the problem is the access token, I've tried it also in another server but both returns the same emails.
I've also tried to get the auth code with seth#gmail.com and the manually I've retrieved the access token:
$token = $client->fetchAccessTokenWithAuthCode($code);
but no way, also doing this it will keeps authenticating me as the other email.
UPDATE:
The thing is getting stranger, I have tried to remove all part of the config file, and I use it only when I have to retrieve the auth code.
So in the request I pass only the access token array, what happens is that I can see the emails also completely removing the access token, so basically the client looks empty at the moment of the request.
(
[auth:Google_Client:private] =>
[http:Google_Client:private] =>
[cache:Google_Client:private] =>
[token:Google_Client:private] => Array
(
[access_token] => no token what so eva
)
[config:Google_Client:private] => Array
(
[application_name] =>
[base_path] => https://www.googleapis.com
[client_id] =>
[client_secret] =>
[redirect_uri] =>
[state] =>
[developer_key] =>
[use_application_default_credentials] =>
[signing_key] =>
[signing_algorithm] =>
[subject] =>
[hd] =>
[prompt] =>
[openid.realm] =>
[include_granted_scopes] =>
[login_hint] =>
[request_visible_actions] =>
[access_type] => online
[approval_prompt] => auto
[retry] => Array
(
)
)
[logger:Google_Client:private] =>
[deferExecution:Google_Client:private] =>
[requestedScopes:protected] => Array
(
)
)
I solved this by updating the client library to the latest version.
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.
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.
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.
I am getting following error while trying to fetch access_token:
The access_token method must be called with a request_token /oauth/access_token?oauth_version=1.0
Following is my code snippet:
require_once('OAuth_functions.php');
$objTwitter = new TwitterOAuth("xxxxx","xxxxxxxxxxxxxxxxxx","xxx-xxx","xxxxxx");
$access_token = $objTwitter->getAccessToken();
While printing the variable $access_token, following response retrieved:
Array
(
[ "1.0" encoding="UTF-8"?>
The access_token method must be called with a request_token
/oauth/access_token?oauth_version=1.0
[amp;oauth_nonce] => xxx
[amp;oauth_timestamp] => 1311491162
[amp;oauth_consumer_key] => xxx
[amp;oauth_token] => xxx-xxx
[amp;oauth_signature_method] => HMAC-SHA1
[amp;oauth_signature] => xxx=
)
I want to implement SIGN IN WITH TWITTER functionality for my site.
I think you need to use $_REQUEST['oauth_verifier'] via callback url.
check https://dev.twitter.com/discussions/7771