Xively provisioning - how does an app request a device feed ID and key? - xively

Xively provisioning - how does an app request a device feed ID and key?
On the "Provisioning" page it says:
"8 An application prompts the user for the serial number of the device they have just activated, the application uses a Master Key and the device serial number to request the device Feed ID and key from Xively."
This seems to suggest there's an API to do this, but I can't find it!
Does anyone know where this is in the docs or how to do this?

To get a feed ID for the device one need to make a Read Device request.

Go to Account | Settings | Add a master key
with Read/Update all permissions.
2) Note down the master key. Now to read all the devices (instances) created for a product (template) use API and key from (1)
URL: https://api.xively.com/v2/products/product_id/devices
X-ApiKey: The key you created in (1)
This API will return all devices with feedId and device keys.
A working example with Curl
include ('sensorui.inc');
include(APP_CLASS_LOADER);
// script to list all devices for a product
$url = "https://api.xively.com/v2/products/XwYNEGj4epo7HXNM0DGK/devices" ;
// API KEY
// This is master key API (from Account | settings page)
// for some reason (bug?) READ only key does not work!
$xheaders = array("X-ApiKey" => "your_master_key");
$cookies = array();
$curl = new \com\yuktix\util\curl\Wrapper($url,$cookies,$xheaders) ;
$curl->setCookies($cookies);
$curl->setXHeaders($xheaders);
// $curl->setDebug();
$response = $curl->doGet();
print_r($response);
$code = ($response["code"] != 200) ? 1 : 0 ;
return $code ;
Returns
rjha#kubuntu13:~/code/bitbucket/sensorui/scripts/xively$ php list-product.php
Array
(
[code] => 200
[response] => {"totalResults":2,"itemsPerPage":30,"startIndex":1,"devices":[{"serial":"SVSN001","activation_code":"xxx","created_at":"2014-02-02T15:05:37Z","activated_at":"2014-02-02T15:12:41Z","feed_id":xxx,"api_key":"xxx"},{"serial":"SVSN002","activation_code":"xxxx","created_at":"2014-02-02T15:05:37Z","activated_at":null,"feed_id":xxxx}]}

Related

Google analytics 4 API with authentication

My website already has universal analytics and we are displaying different analytics profile data on our dashboard by authenticating users. Because each user will have access to a different analytics profile. So the steps we follow in UA are,
Ask the user to authenticate.
Get auth code and create an access token.
Passing access token to listManagementProfiles API to get the list of profiles for the authenticated user.
Based on the selected profile we display the analytics data. (we use google service analytics library)
sample code:
if (!class_exists('Google_Client')) {
require_once '/lib/google-api-php-client-master/src/Google/Client.php';
require_once '/lib/google-api-php-client-master/src/Google/Service/Analytics.php';
}
$this->client = new Google_Client();
$this->client->setApprovalPrompt('force');
$this->client->setAccessType('offline');
$this->client->setClientId('************');
$this->client->setClientSecret('*************');
$this->client->setRedirectUri('*****************');
$this->client->setScopes('https://www.googleapis.com/auth/analytics');
$this->client->setDeveloperKey('*************************');
$this->service = new Google_Service_Analytics($this->client);
$accessToken = $this->client->authenticate($authCode);
if ($accessToken) {
$this->client->setAccessToken($accessToken);
return true;
} else {
return false;
}
Where I'm stuck?
I've checked for the GA4 documentation and followed the steps provided in the doc. I have created the account/property for GA4 in one of my google accounts.
I then enabled the analytics service from google console.
Created service account.
Downloaded JSON file.
Downloaded the google admin client library from here
GA4 sample code:
require 'vendor/autoload.php';
use Google\Analytics\Admin\V1alpha\AnalyticsAdminServiceClient;
use Google\Analytics\Data\V1beta\BetaAnalyticsDataClient;
use Google\Analytics\Data\V1beta\DateRange;
use Google\Analytics\Data\V1beta\Dimension;
use Google\Analytics\Data\V1beta\Metric;
putenv('GOOGLE_APPLICATION_CREDENTIALS=config.json');
$client = new AnalyticsAdminServiceClient();
$accounts = $client->listAccountSummaries();
But this does not require the access_token and without an access token, it allows to fetch the accounts lists. I don't want the manual process of giving access to the service account for each analytics account.
I want my user to authenticate to my website and then only do the rest process based on it.
How can I achieve that?
I also read something that GA4 does not have profiles(views), then how can I access the profile data in GA4? do I need to list down the accounts/properties list to the user for selection?
I need the referral, organic search, users, and session data on my website. What endpoint of GA4 provides this data?
Any other library do I need to use?
I think you are close. You are just mixing oauth and service account.
With your UA analytics code you are using the Google analytics reporting api / google analytics management api to request access of the user to access their Google analytics accounts. You are currently using Oauth2 to request access of a user to access "their" google analytics accounts. These are accounts that they control.
With your GA4 accounts you are connecting to the google analytics admin api though you are currently using a service account.
Service accounts must be pre authorized. They are intended for use with accounts that the developer owns. You need to swtich it to use Oauth2 and not a service account. This way the users will be authenticated to their own account.
Google analytics admin Oauth2
Here is a sample with Oauth2.
<?php
// composer composer require google/analytics-admin
require 'vendor/autoload.php';
use Google\Client;
use Google\Analytics\Admin\V1alpha\AnalyticsAdminServiceClient;
putenv('GOOGLE_APPLICATION_CREDENTIALS=C:\YouTube\dev\credentials.json'); // Installed app credentials.
$credentials = getenv('GOOGLE_APPLICATION_CREDENTIALS');
$myfile = file_get_contents($credentials, "r") ;
$clientObj = json_decode($myfile);
$client = getClient();
$tokenResponse = $client->getAccessToken();
print_r($tokenResponse);
print_r($tokenResponse["access_token"]);
$service = new AnalyticsAdminServiceClient( [
'credentials' => Google\ApiCore\CredentialsWrapper::build( [
'scopes' => [
'https://www.googleapis.com/auth/analytics',
'openid',
'https://www.googleapis.com/auth/analytics.readonly',
],
'keyFile' => [
'type' => 'authorized_user',
'client_id' => $clientObj->installed->client_id,
'client_secret' => $clientObj->installed->client_secret,
'refresh_token' => $tokenResponse["refresh_token"]
],
] ),
] );
$accounts = $service->listAccounts();
foreach ($accounts as $account) {
print 'Found account: ' . $account->getName() . PHP_EOL;
}
function getClient()
{
$client = new Client();
$client->setApplicationName('Google analytics admin beta Oauth2');
$client->setScopes('https://www.googleapis.com/auth/analytics.readonly');
$client->setAuthConfig(getenv('GOOGLE_APPLICATION_CREDENTIALS'));
$client->setAccessType('offline');
// Load previously authorized token from a file, if it exists.
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
$tokenPath = 'tokenAdmin.json';
if (file_exists($tokenPath)) {
$accessToken = json_decode(file_get_contents($tokenPath), true);
$client->setAccessToken($accessToken);
}
// If there is no previous token or it's expired.
if ($client->isAccessTokenExpired()) {
// Refresh the token if possible, else fetch a new one.
if ($client->getRefreshToken()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
$client->setAccessToken($accessToken);
// Check to see if there was an error.
if (array_key_exists('error', $accessToken)) {
throw new Exception(join(', ', $accessToken));
}
}
// Save the token to a file.
if (!file_exists(dirname($tokenPath))) {
mkdir(dirname($tokenPath), 0700, true);
}
file_put_contents($tokenPath, json_encode($client->getAccessToken()));
}
return $client;
}
Note this is a console app, not a web app. You may have to tweek it to work with web but you should just be able to copy your UA auth code and dump the tokens in as i have shown here.
Code shamelessly copied from Simple How to Integrate php with Google analytics admin api.
To fetch Account Summaries using Access Token, you can use Google APIs Client Library for PHP
Here is the working code
<?php
require_once 'vendor/autoload.php';
use Google\Client;
use Google\Service\GoogleAnalyticsAdmin;
$access_token = 'ya29.xxxxxxx';
// Init Google Client and Set Access Token
$client = new Client();
$client->setAccessToken($access_token);
// GA Admin Service
$service = new GoogleAnalyticsAdmin($client);
// Fetch Account Summaries
$summary = $service->accountSummaries->listAccountSummaries();
// Output
print_r($summary->toSimpleObject());
Output
stdClass Object
(
[accountSummaries] => Array
(
[0] => stdClass Object
(
[account] => accounts/XXXXXXX
[displayName] => XXXXXXX
[name] => accountSummaries/XXXXXXX
[propertySummaries] => Array
(
[0] => stdClass Object
(
[displayName] => XXXXXXX GA4 Property
[parent] => accounts/XXXXXXX
[property] => properties/XXXXXXX
[propertyType] => PROPERTY_TYPE_ORDINARY
)
)
)
[1] => stdClass Object
(
[account] => accounts/XXXXXX
[displayName] => XXXXXXX accounts
[name] => accountSummaries/XXXXXX
)
)
)

How to handle Firebase Cloud Messaging onTokenRefresh on the back end

We have a cross-platform app that uses Firebase Cloud Messaging to drive an in-app chat feature. Some users might use the app actively on more than one device. So, whenever a user's device receives an onTokenRefresh trigger, we send that new registration token to the server to be saved against the user. Now say a user already has some registration tokens stored in the server database, how will we know if those tokens were for the same device and should now be deleted or if they are for a different device and we should keep sending to all of them?
I have read the docs on Device Group Messaging, but it looks like too much overhead for our application and it doesn't look like the Firebase server will automatically delete a superseded registration token from the group for you.
If we simply assume all the user's registration tokens on record are active and send to all, can we use the response to decide if we need to prune a token on the server?
{
"multicast_id": 6538766984100364080,
"success": 1,
"failure": 0,
"canonical_ids": 0,
"results": [
{
"message_id": "0:1510294979553090%029da28f029da28f"
}
]
}
According to this answer and some tests against the HTTP API with replaced tokens, it doesn't look like the "success":1 result is a reliable indicator that the token should not be removed, because replaced tokens tend to live on. Also, a "success": 0 result might not be a reliable indicator that we can remove the token, because it might just indicate an ad-hoc network error on a valid, active token.
The API documentation talks about how to interpret an optional registration_id in the result, but it is not clear how this differs from a NotRegistered error and what the best action is to take.
Any insight or best practice on how to handle and manage the arrival of a FCM device token on the server will be much appreciated.
I also came across the exact challenge and had to resolve to a solution:
Storing each token for the user against the device id.
It's interesting enough to know that this function in fact exists in the firebase messaging method. But more surprising is the fact that there's no documentation to handle such scenario.
https://firebase.google.com/docs/reference/android/com/google/firebase/iid/FirebaseInstanceId.html#getId()
So in summary, while sending the new token to the server, also send along the device id returned by the getId() method and use it to enforce uniqueness of token per device.
Problem solved :D
We are going with the approach where we assume all onTokenRefresh ids are new, additional devices that we add to the device list on the server. Then, whenever we send a message we use the returned result to delete or replace deprecated device tokens. Implementation in PHP:
// $devices is a list of the device ids to send to
// 1. send a message to a list of devices
$response = Firebase::request('POST', 'send', ['json' => $this->payloadFor($devices)]);
// 2. check the response to see if we need to make changes to the device list
// if it is a network error, no changes needed
if ($response->getStatusCode() != 200) {
Log::info("FCM http error " . $response->getStatusCode());
return;
}
$body = json_decode($response->getBody(), $asArray = true);
// do we need to dig deeper?
if ($body['failure'] == 0 && $body['canonical_ids'] == 0) return;
if (count($body['results']) != count($devices)) {
Log::info("FCM error : device count not matching result count");
return;
}
// we have errors that need processing, so step through the results list
foreach ($body['results'] as $key => $result) {
if (isset($result['error'])) {
switch ($result['error']) {
case 'NotRegistered':
case 'InvalidRegistration':
$deletedRows = Device::where('token', $devices[$key])->delete();
Log::info("FCM trimmed: $devices[$key]");
break;
default:
Log::info("FCM error " . $result['error']);
break;
}
}
// we need to update some device tokens
if (isset($result['registration_id'])) {
Device::deprecate($devices[$key], $result['registration_id']);
Log::info("FCM replaced: " . $devices[$key]);
}
}

Telegram Bot How to delete or remove a message or media from a channel or group

I want to know an example of removing message or file like a photo
I did not find any functional tutorial in this regard,
There is no such functionality in Telegram Bot API right now.
UPD 2017-05-19: There is an official method deleteMessage, more info:
https://core.telegram.org/bots/api#deletemessage
https://stackoverflow.com/a/43965602/1140438
There is an official support of deleteMessage method in Bot API 3.0. More details here:
https://core.telegram.org/bots/api#deletemessage
https://api.telegram.org/botTOKEN/deleteMessage?chat_id=CID&message_id=MID
As you can see there are two arguments: chat_id and message_id.
You can remove bot's messages or other messages (if bot is admin) except service messages (such as join/leave messages).
On success, it will return following JSON object:
{"ok":true,"result":true}.
If you are trying to remove service message or other user's message, but bot is not an admin:
{"ok":false,"error_code":400,"description":"Bad Request: message can't be deleted"}.
If you are trying to remove non-existent message or its already deleted:
{"ok":false,"error_code":400,"description":"Bad Request: message to delete not found"}
Kindly check with the below code snippet!, the below code have worked for me!
String chatId = String.valueOf(callbackQuery.getMessage().getChatId());
Integer messageId = callbackQuery.getMessage().getMessageId();
DeleteMessage deleteMessage = new DeleteMessage(chatId, messageId);
try {
execute(deleteMessage);
}catch(TelegramApiException tae) {
throw new RuntimeException(tae);
}
you can forward message and save message id, and then remove that message. if you can do it, your message exist.
do it:
try:
mes=bot.forward_message(chat_id=?,from_chat_id=?,message_id=?)
bot.delete_message(chat_id=?,message_id=mes.id)
except:
print("your message deleted")
There are two methods in bot api that let you to edit a message: editMessageText and editMessageCaption. It is not ideal, but you can use it as an alternative.
For example by editing the message to:
"This message is unavailable."
Using python, if you have a CommandHandler() you can read the chat_id and message_id like so:
dispatcher.add_handler(CommandHandler("start", handler_start))
def handler_start(update: Update, context: CallbackContext):
chat_id = update.message.chat_id
message_id = update.message._id_attrs[0]
context.bot.delete_message(chat_id, message_id)
If on php. I send message. Get response from it (message id of bot) And use deleteMessage
<?php
$botToken = "yourBotToken";
$botAPI = "https://api.telegram.org/bot" . $botToken;
$update = json_decode(file_get_contents('php://input'), TRUE);
$msg = $update['message']['text'];
if ($msg == '/start') {
$data = http_build_query([
'text' => "test message (delete this)",
'chat_id' => $update['message']['chat']['id'],
]);
$send = file_get_contents($botAPI . "/sendMessage?{$data}");
$response = json_decode($send), true); // decode response
$message_id = $response['result']['message_id']; // get bots message
// Deleting message
$data_del = http_build_query([
'chat_id' => $update['message']['chat']['id'],
'message_id' => $message_id,
]);
file_get_contents($botAPI . "/deleteMessage?{$data_del}");
}
https://api.telegram.org/botTOKEN/deleteMessage?chat_id=CID&message_id=MID
Example
https://api.telegram.org/bot123456789:zzzzzzzzxxxxxxxxxxyyyyyyyyyy/deleteMessage?chat_id=123456789&message_id=123456,
It is important that the id of the message temine with a (comma) (,) and you can see it in the json when you send the message

Extending Access Token Expiration not functioning

I am at the intermediate level in php and am new with facebook development. I have looked through the facebook documents and Stack Overflow previous comments.
All I basically wanted to do was let the user log in with their Facebook account and display their name.
My php page has a graph, and the page auto refreshes every 2 or 5 min.
I authenticate and get the facebook first_name to put on the page.
$graph = $facebook->api('/me');
echo $graph['first_name'] to get the first name of the user .. (for which I thought that no access token was required).
After about 90 min. I have been receiving the error:
fatal error: Uncaught OAuthException: An active access token must be used to query information about the current user......
and I have no value ( 0 ), in the $facebook->getUser(); parameter
I do know that off line access permission has been depreciated, (and I have have this enabled in my apps advanced settings)
I am trying to get an extended access token. In the FB docs. I see:
https://graph.facebook.com/oauth/access_token?
client_id=APP_ID&
client_secret=APP_SECRET&
grant_type=fb_exchange_token&
fb_exchange_token=EXISTING_ACCESS_TOKEN
I included my information in the link(an existing valid access token and all) and received a access token:
access_token=AAADbZBPuUyWwBAFubPaK9E6CnNsPfNYBjQ9OZC63ZBN2Ml9TCu9BYz89frzUF2EnLttuZAcG2fWZAHbWozrvop9bQjQclxVYle7igvoZCYUAg2KNQLMgNP&expires=4050
Yet this token expired in about 1 hour or so.(....expires=4050)
I assume I am using server side auth because I am using PHP?
I assume you need to enable "deprecate offline_access" in your Apps Advanced Settings page. As this worked for me:
//added code in base_facebook.php inside the facebook class
public function getExtendedAccessToken(){
try {
// need to circumvent json_decode by calling _oauthRequest
// directly, since response isn't JSON format.
$access_token_response =
$this->_oauthRequest(
$this->getUrl('graph', '/oauth/access_token'),
$params = array( 'client_id' => $this->getAppId(),
'client_secret' => $this->getAppSecret(),
'grant_type'=>'fb_exchange_token',
'fb_exchange_token'=>$this->getAccessToken(),
));
} catch (FacebookApiException $e) {
// most likely that user very recently revoked authorization.
// In any event, we don't have an access token, so say so.
return false;
}
if (empty($access_token_response)) {
return false;
}
$response_params = array();
parse_str($access_token_response, $response_params);
if (!isset($response_params['access_token'])) {
return false;
}
return $response_params['access_token'];
}
The token can still be invalid for several reasons, See How-To: Handle expired access tokens.
Hope it helps
There's a bug on this:
https://developers.facebook.com/bugs/241373692605971
But, another question on SO has a workaround (user uninstalls and re-installs):
fb_exchange_token for PHP only working once user removes app

PHP SDK: How do I capture the access token after user auths app?

This is for a canvas app on the Facebook Platform using the new(est) Facebook PHP SDK.
We are using the PHP example from the Facebook tutorial (https://developers.facebook.com/docs/appsonfacebook/tutorial/) to trigger the OAuth dialog and get the test user to the redirect URL.
At the redirect URL, we use the PHP example from the Facebook signed request docs page (https://developers.facebook.com/docs/authentication/signed_request/) and our test users can successfully authorize the app.
However, after the test user auths the app, we are not able to capture the access token and its expiration. We can see it in the address bar appended to the redirect URL, but it does not show up in the $_REQUEST array. If we add {$access_token = $facebook->getAccessToken();} to the redirect URL page, it shows a value for the access token, but the value it shows is not the full token string that we see when we click on Show Token in the Test User Roles page (which we believe is the correct access token for the test user).
Here is an example of the redirect URL with an access token appended:
http://karmakorn.com/karmakorn/alpha20/kk-fb-auth.php#access_token=126736467765%7C2.AQDavId8oL80P5t9.3600.1315522800.1-100002908746828%7CJICJwM1P_97tKmqkEO5pXDCf-7Y&expires_in=6008
Here is what var_dump shows for the $REQUEST array for that same page:
array(3) { ["_qca"]=> string(26) "P0-709927483-1291994912966" ["__switchTo5x"]=> string(2) "30" ["PHPSESSID"]=> string(26) "euois02ead39ijumca7nffblh2" }
We have no idea why the $_REQUEST array varies from the values appended to the URL, and more importantly -- how to capture the access token and its expiration date.
Can someone show us a working example of how they capture this data after running the parse_signed_request($signed_request, $secret) function on the redirect page? Thanks!
ADDITIONAL INFO:
Here is the pertinent code from A) our test index page, and B) our test redirect page. If we use our text index page as the redirect url it gets stuck in an endless loop -- because the user is never identified.
A) Index Page
// Create kk-fb app instance
$facebook = new Facebook(array(
'appId' => KKFB_ID,
'secret' => KKFB_KY,
'oauth' => true,
));
$app_id = KKFB_ID;
$secret = KKFB_KY;
$canvas_auth = 'http://karmakorn.com/karmakorn/alpha20/kk-fb-auth.php';
$auth_url = "https://www.facebook.com/dialog/oauth?"
. "client_id=" . $app_id
. "&redirect_uri=" . urlencode($canvas_auth)
. "&response_type=token"
. "&scope=email,publish_stream";
$signed_request = $_REQUEST["signed_request"];
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$data = json_decode(base64_decode(strtr($payload, '-_', '+/')), true);
if (empty($data["user_id"])) {
echo("<script> top.location.href='" . $auth_url . "'</script>");
} else {
echo ("Welcome User: " . $data["user_id"]);
}
B) Redirect Page
// Create kk-fb app instance
$facebook = new Facebook(array(
'appId' => KKFB_ID,
'secret' => KKFB_KY,
'oauth' => true,
));
$app_id = KKFB_ID;
$secret = KKFB_KY;
$signed_request = $_REQUEST["signed_request"];
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$data = json_decode(base64_decode(strtr($payload, '-_', '+/')), true);
$user = $facebook->getUser();
$access_token = $facebook->getAccessToken();
echo "User: $user <br>";
echo "Access Token: $access_token <br>";
echo "Signed Request: $signed_request <br>";
var_dump($_REQUEST);
Here is what shows up as these echo results:
User: 0
Access Token: 126736467765|**SECRET**
Signed Request:
array(3) { ["_qca"]=> string(26) "P0-709927483-1291994912966" ["_switchTo5x"]=> string(2) "30" ["PHPSESSID"]=> string(26) "frugi545cdl15gjind1fnv6pq1" }
Interestingly, when the test user goes back to the index page the if condition is satisfied and we can get the correct access token:
Welcome User: 100002908746828
Access Token: 126736467765|2.AQBgcyzfu75IMCjw.3600.1315544400.1-100002908746828|m5IYEm976tJAkbTLdxHAhhgKmz8
Obviously, we are still missing something!? Also, we need to learn how to get the expiration time as a variable too so we can store both of these in our database.
OK, let's try this again.
Server-side vs Client-side Authentication
You are exclusively using the PHP SDK, so you want to do server-side authentication, where the authentication code is sent to the server over HTTP via the URL. This will allow you to fetch an access token for the user on the first page load after auth (in your case, the redirect page). The auth_url you are currently constructing is setting response_type=token, which forces the redirect to use client-side auth mode and set the token in the URL fragment instead of in the query. You should remove that parameter completely. In fact, I highly recommend you just use the PHP SDK instead of constructing that URL yourself. See example below.
Application Access Tokens
The odd-looking access token 126736467765|SECRET is your application access token, which is composed of your app ID and secret key. The application access token is returned by getAccessToken() if no user access token is available (because some API calls require at least some sort of access token). This also means that you've revealed your secret key to the world via this blog post, so you should reset your app secret otherwise anyone will be able to make API calls on your behalf. I highly recommend you elide parts of your access tokens if you share them with others.
Token Expiration
The OAuth 2.0 flow and v3.1.1 of the PHP SDK don't make determining the expiration time of a token all that easy. I would suggest attempting to make the API call, and then refreshing the token if the API call fails with an OAuthException. Tokens can be invalid even if they haven't expired, so this deals with more cases. However, if you still want to maintain the expiration date on your end, you might just want to extract it from the token itself. If you have an expiring token, then the expiration timestamp will be contained within that string. Here's a function I put together quickly to extract that:
function extractExpirationFromToken($access_token) {
$segments = explode('|', $access_token);
if(count($segments) < 2) { return 0; }
$segments = explode('.', $segments[1]);
if(count($segments) < 4) { return 0; }
$expires = $segments[3];
$dash_pos = strrpos($expires, '-');
if($dash_pos !== false) {
$expires = substr($expires, 0, $dash_pos);
}
return $expires;
}
New Index Page Code
// Create kk-fb app instance
$facebook = new Facebook(array(
'appId' => KKFB_ID,
'secret' => KKFB_KY,
));
$canvas_auth = 'http://karmakorn.com/karmakorn/alpha20/kk-fb-auth.php';
$auth_url = $facebook->getLoginUrl(array(
'scope' => 'email,publish_stream',
'redirect_uri' => $canvas_auth, // you could just redirect back to this index page though
));
$user = $facebook->getUser();
if (empty($user)) {
echo("<script> top.location.href='" . $auth_url . "'</script>");
} else {
echo ("Welcome User: " . $user);
}
Redirect Page
I don't think you need this page at all. You could just redirect the user back to your original index page.
// Create kk-fb app instance
$facebook = new Facebook(array(
'appId' => KKFB_ID,
'secret' => KKFB_KY,
));
$user = $facebook->getUser();
$access_token = $facebook->getAccessToken();
// also copy the function definition given earlier
$expiration = extractExpirationFromToken($access_token);
echo "User: $user <br>";
echo "Access Token: $access_token <br>";
echo "Expiration: $expiration <br>";
echo "Request: <br>";
var_dump($_REQUEST);
You can use the facebook build in method getAccessToken() for example;
$access_token = $facebook->getAccessToken();
This will give you the access token to your variable, now if you are getting it empty, remember to first check if the fuid is being properly catch, if it isn't you might need to review your settings be sure your "App Domain" is set this part is very important after setting it correctly you need to reset your app secret, then set your new values in your auth code. Hope this help, let me know :)
pd. Also remember to keep the scope of your variables visible in your whole php file or class.
Problem
The access_token in your pasted URL is not part of the query string, but instead contained in the URL fragment (after the #). URL fragments are not sent to the web server, and are readable only by client-side code like Javascript. Therefore the PHP SDK only sees http://karmakorn.com/karmakorn/alpha20/kk-fb-auth.php, which is why $_REQUEST does not contain an access_token key.
Questions / Notes
What are you using for your redirect_uri? I think you want to be using something like http://apps.facebook.com/your_canvas_url/
You shouldn't need to call parse_signed_request yourself or copy any code from the signed request page. The PHP SDK will do that for you. Just call:
$facebook = new Facebook(array(
'appId' => '…',
'secret' => '…',
));
$access_token = $facebook->getAccessToken();
Possible solutions
Also use the Facebook Javascript SDK. You can start by adding its <script> tag in your destination page (kk-fb-auth.php) (see the docs for full details; don't forget to set oauth: true). The JS SDK should set a cookie (named fbsr_126736467765) which the PHP SDK will be able to read via $_REQUEST or $_COOKIE on subsequent page loads.
If you want to do this with PHP, you can get the user's access token with a separate call to the Graph API at your redirect_uri. For this you need to change the response_type of your $auth_url in your index page to "code" or "code token".
Then, at your redirect page, Facebook will add a "code" parameter in the querystring. This API call will return you the full access_token and expiration time:
https://graph.facebook.com/oauth/access_token?
client_id=YOUR_APP_ID&
redirect_uri=YOUR_URL&
client_secret=YOUR_APP_SECRET&
code=$_REQUEST['code']
For more information you can refer to the docs on authentication.

Resources