get a new short-lived user access_token - access-token

I need to renew a long-lived access token. I read
Renew long lived access token server side topic and wrote a code as follows:
<?php
$code = $_REQUEST["code"];
if(empty($code)) {
$dialog_url = "https://www.facebook.com/dialog/oauth?"
. "client_id=$app_id"
. "&redirect_uri=$my_url"
. "&scope=..."
;
echo("<script> top.location.href='" . $dialog_url . "'</script>");
}
else
{
$response = file_get_contents("https://graph.facebook.com/oauth/access_token?"
. "client_id=$app_id"
. "&redirect_uri=$my_url"
. "&client_secret=$app_secret"
. "&code=$code"
);
$params = null;
parse_str($response, $params);
$access_token=$params['access_token'];
$response = file_get_contents("https://graph.facebook.com/oauth/access_token?"
. "client_id=$app_id"
. "&client_secret=$app_secret"
. "&redirect_uri=$my_url"
. "&grant_type=fb_exchange_token"
. "&fb_exchange_token=$access_token"
);
}
?>
On the first invocation it acquires 60-days access token all right. I expect that on the next invocations it would acquire another (may be with the same name) 60-days tokens, and I would see in the Debugger https://developers.facebook.com/tools/debug that issue time and expiration time changes, but the times do not change. What's wrong with my scenario?

Have you compared the tokens to each other? Facebook will send you back the existing access token when the same call is made in less than 24 hours. Also, tokens are set to not expire if you have also requested page tokens for the user. See my answer here: Facebook Page Access Tokens - Do these expire? for more info on this subject.
One way you can be sure to get a new token each time is if you revoke access by making an http DELETE call to /PROFILE_ID/permissions and then requesting a new token. The only bad thing about this is it will require you to put the user through the oAuth dialog again.

Related

Slow Response Time - Google APIs Geocoding and Recaptcha

Regarding my Google APIs, recaptcha and geocoding, I've checked the configuration of my Google Account and everything looks fine. The queries all reach an OK status. HOWEVER, the queries all take more than a minute to get a response. Like I said, I haven't found anything abnormal and quotas are neither being reached nor exceeded. Why are the response times so slow? Is this coming from Google? The fact that I don't have billing activated on my account?
How else can I determine what is causing this and reduce response time?
ETA:
Our configuration files were checked over yesterday and they are perfectly fine (public as well as private keys)
The methods I used were JSON or CURL and yet, the problem of excessive response times still persists.
Example Get :
$address = urlencode($address);
$url = "https://maps.google.com/maps/api/geocode/json?key=XXXXXXXKEYXXXXXXX&sensor=false&address=$address";
$resp_json = file_get_contents($url);
$resp = json_decode($resp_json, true);
$lati = $resp['results'][0]['geometry']['location']['lat'];
$longi = $resp['results'][0]['geometry']['location']['lng'];
$formatted_address = $resp['results'][0]['formatted_address'];
echo $resp['status'].">>".$formatted_address;
Exemple Curl:
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$parsed = curl_exec($ch);
curl_close($ch);
print_r($parsed);

Obtaining a Facebook auth token for a command-line (desktop) application

I am working for a charity which is promoting sign language, and they want to post a video to their FB page every day. There's a large (and growing) number of videos, so they want to schedule the uploads programmatically. I don't really mind what programming language I end up doing this in, but I've tried the following and not got very far:
Perl using WWW::Facebook::API (old REST API)
my $res = $client->video->upload(
title => $name,
description => $description,
data => scalar(read_file("videos/split/$name.mp4"))
);
Authentication is OK, and this correctly posts a facebook.video.upload method to https://api-video.facebook.com/restserver.php. Unfortunately, this returns "Method unknown". I presume this is to do with the REST API being deprecated.
Facebook::Graph in Perl or fb_graph gem in Ruby. (OAuth API)
I can't even authenticate. Both of these are geared towards web rather than desktop applications of OAuth, but I think I ought to be able to do:
my $fb = Facebook::Graph->new(
app_id => "xxx",
secret => "yyy",
postback => "https://www.facebook.com/connect/login_success.html"
);
print $fb->authorize->extend_permissions(qw(publish_stream read_stream))->uri_as_string;
Go to that URL in my browser, capture the code parameter returned, and then
my $r = $fb->request_access_token($code);
Unfortunately:
Could not fetch access token: Bad Request at /Library/Perl/5.16/Facebook/Graph/AccessToken/Response.pm line 26
Similarly in Ruby, using fb_graph,
fb_auth = FbGraph::Auth.new(APP_ID, APP_SECRET)
client = fb_auth.client
client.redirect_uri = "https://www.facebook.com/connect/login_success.html"
puts client.authorization_uri(
:scope => [:publish_stream, :read_stream]
)
Gives me a URL which returns a code, but running
client.authorization_code = <code>
FbGraph.debug!
access_token = client.access_token!
returns
{
"error": {
"message": "Missing client_id parameter.",
"type": "OAuthException",
"code": 101
}
}
Update: When I change the access_token! call to access_token!("foobar") to force Rack::OAuth2::Client to put the identifier and secret into the request body, I get the following error instead:
{
"error": {
"message": "The request is invalid because the app is configured as a desktop app",
"type": "OAuthException",
"code": 1
}
}
How am I supposed to authenticate a desktop/command line app to Facebook using OAuth?
So, I finally got it working, without setting up a web server and doing a callback. The trick, counter-intuitively, was to turn off the "Desktop application" setting and not to request offline_access.
FaceBook::Graph's support for posting videos doesn't seem to work at the moment, so I ended up doing it in Ruby.
fb_auth = FbGraph::Auth.new(APP_ID, APP_SECRET)
client = fb_auth.client
client.redirect_uri = "https://www.facebook.com/connect/login_success.html"
if ARGV.length == 0
puts "Go to this URL"
puts client.authorization_uri(:scope => [:publish_stream, :read_stream] )
puts "Then run me again with the code"
exit
end
if ARGV.length == 1
client.authorization_code = ARGV[0]
access_token = client.access_token! :client_auth_body
File.open("authtoken.txt", "w") { |io| io.write(access_token) }
exit
end
file, title, description = ARGV
access_token = File.read("authtoken.txt")
fb_auth.exchange_token! access_token
File.open("authtoken.txt", "w") { |io| io.write(fb_auth.access_token) }
me = FbGraph::Page.new(PAGE_ID, :access_token => access_token)
me.video!(
:source => File.new(file),
:title => title,
:description => description
)
Problem is in your case that for OAuth you'll need some endpoint URL which is publicly reachable over the Internet for Facebook servers, which can be a no-go for normal client PCs, or a desktop application which is capable of WebViews (and I assume, command line isn't).
Facebook states at https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#login that you can build a desktop client login flow, but only via so-called WebViews. Therefore, you'd need to call the OAuth endpoint like this:
https://www.facebook.com/dialog/oauth?client_id={YOUR_APP_ID}&redirect_uri=https://www.facebook.com/connect/login_success.html&response_type=token&scope={YOUR_PERMISSION_LIST}
You then have to inspect the resulting redirected WebView URL as quoted:
When using a desktop app and logging in, Facebook redirects people to
the redirect_uri mentioned above and places an access token along with
some other metadata (such as token expiry time) in the URI fragment:
https://www.facebook.com/connect/login_success.html#access_token=ACCESS_TOKEN...
Your app needs to detect this redirect and then read the access token out of the URI using the mechanisms provided by the OS and development framework you are using.
If you want to do this in "hacking mode", I'd recommend to do the following.:
As you want to post to a Page, get a Page Access Token and store it locally. This can be done by using the Graph Explorer at the
https://developers.facebook.com/tools/explorer?method=GET&path=me%2Faccounts
endpoint. Remember to give "manage_pages" and "publish_actions" permissions.
Use cURL (http://curl.haxx.se/docs/manpage.html) to POST the videos to the Graph API with the Access Token and the appropriate Page ID you acquired in step 1 like the following:
curl -v -0 --form title={YOUR_TITLE} --form
description={YOUR_DESCRIPTION} --form source=#{YOUR_FULL_FILE_PATH}
https://graph-video.facebook.com/{YOUR_PAGE_ID}/videos?access_token={YOUR_ACCESS_TOKEN}
References:
https://developers.facebook.com/docs/graph-api/reference/page/videos/#publish
https://developers.facebook.com/docs/reference/api/video/
From the facebook video API reference:
An individual Video in the Graph API.
To read a Video, issue an HTTP GET request to /VIDEO_ID with the
user_videos permission. This will return videos that the user has
uploaded or has been tagged in.
Video POST requests should use graph-video.facebook.com.
So you should be posting to graph-video.facebook.com if you are to upload video.
You also need extended permissions from the user or profile you'll be uploading to, in this case you need video_upload this is going to be requested once only, when the user currently logged in is asked for such permission for the app.
And your endpoint should be:
https://graph-video.facebook.com/me/videos
If you always want to post to a specific user than you'll have to change the endpoint part from /me to the User ID or page ID.
Here's a sample (in PHP):
$app_id = "YOUR_APP_ID";
$app_secret = "YOUR_APP_SECRET";
$my_url = "YOUR_POST_LOGIN_URL";
$video_title = "YOUR_VIDEO_TITLE";
$video_desc = "YOUR_VIDEO_DESCRIPTION";
$code = $_REQUEST["code"];
if(empty($code)) {
$dialog_url = "http://www.facebook.com/dialog/oauth?client_id="
. $app_id . "&redirect_uri=" . urlencode($my_url)
. "&scope=publish_stream";
echo("<script>top.location.href='" . $dialog_url . "'</script>");
}
$token_url = "https://graph.facebook.com/oauth/access_token?client_id="
. $app_id . "&redirect_uri=" . urlencode($my_url)
. "&client_secret=" . $app_secret
. "&code=" . $code;
$access_token = file_get_contents($token_url);
$post_url = "https://graph-video.facebook.com/me/videos?"
. "title=" . $video_title. "&description=" . $video_desc
. "&". $access_token;
echo '<form enctype="multipart/form-data" action=" '.$post_url.' "
method="POST">';
echo 'Please choose a file:';
echo '<input name="file" type="file">';
echo '<input type="submit" value="Upload" />';
echo '</form>';
Although I'm concerned about the upload speed if the videos are too big, but I'm guessing your customer has already sorted that out (compress/optimize/short videos etc.)
I've made you a demo here. Go to my website (I own that domain) and try to upload a video. I tried with this one which is a relatively small 4Mb file. Be sure that this script will only try to upload a video, nothing more (to the FB profile you are currently logged in, that is) but, if you are still concerned, copy my snippet, upload it to your own server (with PHP support of course) and create a test app where the site url is that domain and be sure to specify in the $my_url variable your endpoint which is basically the full path to your script receiving responses from facebook:
http://yourdomain.com/testfb.php
If you still want to do it on a desktop app then you have to go to developer.facebook.com on your app settings:
Settings > Advanced
And look for the first option:
And enable that switch so that facebook allows you to POST from a desktop or native app instead of a web server.
Note: I'm not an expert on Ruby, but the above working PHP code should be pretty obvious and easy to port to it.
as far as I recall, what you want isn't really possible without some kind of endpoint that can receive a callback from facebook.
If you can finagle an oauth token, from say the Graph API Explorer, then it becomes pretty trivial to use a gem like koala to upload your video.
here's the salient bit:
#graph = Koala::Facebook::API.new(access_token)
#graph.put_video(path_to_my_video)
I've made you a sample project here: fb-upload-example

how to check that user is inactive for some specific duration?

I want to log out the user if he is inactive for some specific duration. USing sess_expiration in config file, it gives the timing from login not from inactive state.
So how can I do this using codeigniter?
you can store the time in a session when the user logging in like this:
$_SESSION['loginTime'] = time();
and when the user do any action in the system, check if the user exceed the specified time
if($_SESSION['loginTime'] < time()+$yourtime){
logout();
}else{
$_SESSION['loginTime'] = time();
}

Opencart cart across multiple stores with different subdomains

Hi have a single opencart install setup with several stores with different subdomains (all under the same domain). I want customers to be able to put items in the cart on one site, then move onto the next and put in more or even subtract, till eventually a customer checkouts out on any store. Note products might appear in one store but not another.
I notice opencart does this somewhat. ie it will bring products already in the cart to the next store but only if the products appear in both stores. Further if a customer then deletes one of the items and moves back to the same store, they product reappears.
First Problem seems to firstly be products in the cart are being displayed through what i guess is a query that selects products by store_id. I have had a hard look to see if i can find anything but am at a loss.
Second problem seems to be with the contents of the session. I am still learning php and am a bit confused of how to even attempt to modify how the session works.
Can anyone please provide some guidance on how i can go about fixing/changing this.
OpenCart stores all these information in you PHP session. Since your stores are located under different subdomains, the PHP session changes when you switch from one store to another.
So the first thing you need to do is to share the session between all subdomains. By default, PHP uses the 'PHPSESSID' cookie to propagate session data across multiple pages, and by default it uses the current top-level domain and subdomain in the cookie declaration.
Example: www.domain.com
The downside to this is that the session data can't travel with you to other subdomains. So if you started a session on www.domain.com, the session data would become unavailable on forums.domain.com. The solution is to change the domain PHP uses when it sets the 'PHPSESSID' cookie.
Assuming you have an init file that you include at the top of every PHP page, you can use the ini_set() function. Just add this to the top of your init page:
ini_set('session.cookie_domain',
substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));
This line of code takes the domain and lops off the subdomain.
Example: forums.domain.com -> .domain.com
Now, every time PHP sets the 'PHPSESSID' cookie, the cookie will be available to all subdomains!
You might also need to make some little modifications to the OpenCart's core in order to make it work.
Have fun :)
After Tohids help I have the following solution, hopefully it helps others. I added the cookie_domain code line to the session.php file and also added or changed the cookie name wherever the setcookie function was used to cover the currency and language cookies.
open \system\session.php
find;
ini_set('session.use_cookies', 'On');
ini_set('session.use_trans_sid', 'Off');
insert after;
ini_set('session.cookie_domain', substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));
open \index.php
find;
if (!isset($request->cookie['language']) || $request->cookie['language'] != $code) {
setcookie('language', $code, time() + 60 * 60 * 24 * 30, '/', $request->server['HTTP_HOST']);
}
replace with;
if (!isset($request->cookie['language']) || $request->cookie['language'] != $code) {
setcookie('language', $code, time() + 60 * 60 * 24 * 30, '/', substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));
}
find;
if (isset($request->get['tracking']) && !isset($request->cookie['tracking'])) {
setcookie('tracking', $request->get['tracking'], time() + 3600 * 24 * 1000, '/');
}
replace with;
if (isset($request->get['tracking']) && !isset($request->cookie['tracking'])) {
setcookie('tracking', $request->get['tracking'], time() + 3600 * 24 * 1000, '/', substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));
}
open system\currency.php
find;
if (!isset($this->request->cookie['currency']) || ($this->request->cookie['currency'] != $currency)) {
setcookie('currency', $currency, time() + 60 * 60 * 24 * 30, '/', $this->request->server['HTTP_HOST']);
}
replace with;
if (!isset($this->request->cookie['currency']) || ($this->request->cookie['currency'] != $currency)) {
setcookie('currency', $currency, time() + 60 * 60 * 24 * 30, '/', substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));
}
Very Easy Solution! Share the login session across the subdomains
OPEN FILE: system/library/session.php
FIND LINE: session_set_cookie_params(0, '/');
APPEND : session_set_cookie_params(0, '/','.DOMAIN.COM);
Make sure to include the period "." before DOMAIN.COM
That's it... Now login sessions started on www.domain.com is shared with www.sub.domain.com

Using Stored Twitter access_tokens with Twitterizer

I am using C3 & the latest twitterizer api. I have managed to get the user to authenticate & authorize my twitter application after which I persist only the access_token, access_token_secret and access_token_verifier.
The problem I have now is that when the user returns ( at a later stage, cookies removed / expired ), they identify themselves using our own credentials system, and then I attempt to see if their twitter credentials are still valid. I do this by calling the following method
OAuthTokens t = new OAuthTokens();
t.ConsumerKey = "XXX"; // my applications key
t.ConsumerSecret = "XXX";// my applications secret
t.AccessToken = "XXX";// the users token from the DB
t.AccessTokenSecret = "XXX";//the users secret from the DB
TwitterResponse<TwitterUser> resp = TwitterAccount.VerifyCredentials(tokens);
This is the error I get : "error":"Could not authenticate with OAuth.","request":"/1/account/verify_credentials.json"
I know my tokens are valid because if I call this method :
TwitterResponse<TwitterUser> showUserResponse = TwitterUser.Show(tokens, CORRECT_SCREEN_NAME_HERE);
with my screen name passed in and the same OAuth tokens, it returns correctly.
Any Ideas?
C# -> v4.0.30319
Twitterizer -> 2.4.0.2028
In your code, you're defining tokens as t, but when you call VerifyCredentials you're passing it tokens. Is that just an error in your sample code?

Resources