Why Twitter API requests user's permission each time? - php

I'm using Twitter API with CodeBird (PHP).
Here is a quote from Twitter's docs:
so for users already signed in to twitter.com who have authorized the application, no UI is shown - instead, they are automatically redirected back to the application.
In the case where the user is already signed in to twitter.com and has granted access to the website, this redirect happens immediately.
https://dev.twitter.com/web/sign-in/desktop-browser
Why this does not work for me? Twitter asks user's permission for each time.
My code for obtaining authorization URL:
\Codebird\Codebird::setConsumerKey(
$this->config['twitter']['consumer_key'],
$this->config['twitter']['consumer_secret']
);
$cb = \Codebird\Codebird::getInstance();
$reply = $cb->oauth_requestToken([
'oauth_callback' => 'https://***/login/twitter'
]);
$cb->setToken($reply->oauth_token, $reply->oauth_token_secret);
$this->session->twitter_oauth_token = $reply->oauth_token;
$this->session->twitter_oauth_token_secret = $reply->oauth_token_secret;
$this->session->twitter_oauth_verify = true;
return $this->redirect($cb->oauth_authorize());

Solved!
oauth_authorize will always ask user for a permission.
oauth_authenticate will request it only once and will perform automatic redirect, if access already granted.

Related

Facebook PHP - posting error to timeline but not to page

I am trying to post to a Facebook account (with permissions) using the PHP
API. I am giving our users two options - posting to the Feed, and posting
to a specific facebook page. I am getting an error in the first case, but
not in the second case. In the code below:
$access_token is the access token I got back from linking to my app. It's of type
"User", and has the following permissions:
email
pages_show_list
business_management
pages_read_engagement
pages_manage_metadata
pages_read_user_content
pages_manage_ads
pages_manage_posts
pages_manage_engagement
public_profile
Where $page_token is, well, a "Page" type token, with the same set of permissions.
When I post to the page, it works fine. But when I try to post to the timeline, I get
the error:
Graph Error 200 : [Timeline]: [(#200) If posting to a group, requires app being
installed in the group, and either publish_to_groups permission with user token,
or both pages_read_engagement and pages_manage_posts permission with page token;
If posting to a page, requires both pages_read_engagement and pages_manage_posts
as an admin with sufficient administrative permission]
I'm not trying to post to a group, I'm posting to an account's timeline. And, per the
access token debugger, I have the permissions requested anyway. What's going on?
My code is below:
$linkData = [
'link' => $link_to_post,
'appsecret_proof' => $app_secret_proof
];
if ( POSTING TO TIMELINE )
{
$token = $access_token;
$post_to = "/me/feed";
}
else
{
$page_id = $page_id;
$token = $page_token;
$post_to = "/$page_id/feed";
}
// THIS THROWS THE EXCEPTION:
$response = $this->fb->post($post_to, $linkData, $token);
You can not post to a personal timeline via API any more, that was removed ages ago already. (With introduction of API v2.4, if I remember correctly.)
You can only use the Share or the Feed dialog, to offer the user a way to actively share / make a post themselves, https://developers.facebook.com/docs/sharing/web

Cannot add to another users calendar

I am attempting to allow a user add items to the calendars of other users.
A user logs in and get the token as follows
const AUTHORIZE_ENDPOINT = '/oauth2/v2.0/authorize';
const TOKEN_ENDPOINT = '/oauth2/v2.0/token';
const SCOPES = 'profile openid email User.Read Calendars.ReadWrite Calendars.Read Calendars.Read.Shared Calendars.ReadWrite Calendars.ReadWrite.Shared';
$graph = new Graph();
$graph->setAccessToken($token);
$response = $graph->createRequest("GET", "/me")->setReturnType(Model\User::class)->execute();
The logged in user can add to their own calendar using
$request = $graph->createRequest("post", '/me/events');
$request->attachBody($data);
$response = $request->execute();
But, when I try to add to another user with
$request = $graph->createRequest("post", '/anotheruser/events');
$request->attachBody($data);
$response = $request->execute();
I get the message
Resource not found for the segment
Have done the admin auth consent, so all should be fine.
Any suggestions?
If you want to access another user's data you have to use the following url:
/users/{id | userPrincipalName}
Your request was just in the wrong form and you ended up sending a request to an non existing resource, thus Graph didn't know what to do.
In your case you just need to prepend /users (for more information see documentation).
So your request could look like this:
$request = $graph->createRequest("post", '/users/anotheruser/events');
Keep in mind that if you are logged in as a user (token on behalf of a user), the calendar you try to access to must have been shared with the logged in user. Otherwise it will fail due to missing privileges as Graph only allows to edit Calendars that are shared with the user. You also need the Permissions Calendars.Read.Shared and/or Calendars.ReadWrite.Shared (which you seem to already have aquired).
Calendar sharing is unnecessary if you gain access without a user as you then automatically have full access to all users.
Currently the Graph API only supports access to shared Calendars but no operations to edit/change the sharing status or see which Calendars are shared with a user. However you can change the sharing status manually over outlook or the powershell.
Url should be something like Users('anotheruser')/events. Since you are directly saying anotheruser/events. The service is not recognizing another user as a valid segment and throwing the error.

Best practice to save the user's oauth_token and oauth_token_secret - Twitter API

I am creating a Twitter API application(using PHP libray Abraham\TwitterOAuth). when users authenticate the app I can get the oauth_token and oauth_token_secret for that user.
So now where to save those tokens for later use so that users don't have authenticate the app again and again.
Can i save them in cookies ?
UPDATE
#JánHalaša,
Hi, Thanks for your reply. I posted this question at three sites but not get any answer or comment So thanks:). Here is some more detail about the app.
I am using "PHP Abraham\TwitterOauth" Libray (uses Oauth2). My application have "read and write" permissions. It gives users ability to mute or unmute any user. So here is whole process.
I ask user to signin, When user click on signin he asked to authenticate the app by Twitter.
2.Once he authenticate the app. He is redirected to callback url. Where i request the user's oauth_token and oauth_token_secret. And i store those tokens in cookies with little encryption. Some code from callback.php.
$token = $connection->oauth(
'oauth/access_token', [
'oauth_verifier' => $oauth_verifier
]
);
$token['oauth_token']=openssl_encrypt($token['oauth_token'],"AES-128-ECB",$salt);
$token['oauth_token_secret']=
openssl_encrypt($token['oauth_token_secret'],"AES-128-ECB",$salt);
setcookie('oauth_token', $token['oauth_token'],time() + (86400 * 30));
setcookie('oauth_secret', $token['oauth_token_secret'],time() + (86400 *30));
header('location:'mute_now.php');
die();
3.Now i redirect the users to a mute_now.php page. Where i decrypt these cookies and use the oath_token and oauth_secret to get data from twitter on user's behalf. some_code from mute_now.php is
$token['oauth_token'] = openssl_decrypt($_COOKIE['oauth_token'],"AES-128-ECB",$salt);
$token['oauth_token_secret'] = openssl_decrypt($_COOKIE['oauth_token_secert'],"AES-128-ECB",$salt);
$twitter = new TwitterOAuth(
$config['consumer_key'],
$config['consumer_secret'],
$token['oauth_token'],
$token['oauth_token_secret']
);
$user_info = $twitter->get(
"account/verify_credentials"
);
$mutes = $twitter->get(
"mutes/users/list", ['include_entities'=>false,'skip_status'=>true]
);
So now if user come to my website again. I check the cookie. And if cookies are there . He don't need to authenticate the app again i directly redirect hime to mute_now.php and use those cookies to get oauth_token and oauth_token_secert
My main concern is about security. I know user can't use those tokens without the application credentials(consumer_key and consumer_secret). But i still concern about security. Should i use any encryption library like "defuse/php-encryption" before sending cookie. Or any other suggestion Please?

facebook sso state check: CSRF state token does not match one provided

What are the basic steps for setting up a pure server flow facebook SSO, the docs are as usual a little ambiguous?
I set up the flow with javascript popups only to later realise you are not allowed to customise the login buttons.. which when you stick them next google and twitter sso the signin box look terrible.
http://www.codecademy.com/ seem to direct to their own server which then forwards onto a URL like this:
https://www.facebook.com/dialog/oauth?response_type=code
&client_id=212500508799908&
redirect_uri=http%3A%2F%2Fwww.codecademy.com%2Fauth%2Ffacebook%2Fcallback&state=8aac5bc63c5afe8fbabe572021e7750579fefd898d7b4316&
scope=email%2Cpublish_actions
How is this URL being generated? In the facebook docs there is a function "getLoginUrl".. is this being called which generates the correct URL?
I tried directing the user directly from their browser to:
var href = 'https://www.facebook.com/dialog/oauth?' +
'client_id='+app_id+'&'+
'redirect_uri=http://www.mysite.net/authenticate_facebook.php&'+
'scope=email&';+
'state='+$('body').attr('unique');
But the at the facebook php then the following recieving code resulted in errors about the 'state' not matching... I am assuming that the state is not just a random value generate by my server and must be aquired from the facebook server?
require_once(WEBROOT_PRIVATE.'authenticate/facebook-php-sdk/src/facebook.php');
$config = array(
'appId' => 'xxx',
'secret' => 'xxx',
'fileUpload' => false,
'allowSignedRequest' => false
);
$facebook = new \Facebook($config);
$user_id = $facebook->getUser();
if($user_id)
{
try
{
$user_profile = $facebook->api('/me','GET');
}
catch(FacebookApiException $e)
{
error_log($e->getType(), 0);
error_log($e->getMessage(), 0);
}
}
SO, is this correct flow:
1 - Direct the user to my server facebook_auth.php
2 - facebook_auth.php generate the get url and forwards the user onto it
3 - The user, if required logs into facebook, allows my app
4 - my facebook_auth.php script then checks the tokens and talks server to server with facebook to verify the rest
5 - my website then logs the user in
I had a similar issue last week, and tracked it down to the state field being overwritten by multiple calls to getLoginUrl(). Each time you call getLoginUrl(), a new state token is generated in the SDK and stored in the $_SESSION (it's just a random value), so if you call it twice and the user uses the first link to log in, the second call will have reset the SDK's internal state token, and you will get this error in your logs.
The SDK looks for the same state token in the URL coming back after Facebook authorizes the user and redirects them back to your site, and if it doesn't match it will log this error (here's a link to the source).

How to post programatically to your own facebook page?

My situation is the following.
I am the owner of a facebook app,and a facebook page.I would like to programatically(from code) post to this facebook page.
As far as I know I need a facebook app to do that so I created one.
I am using the facebook php sdk and code igniter.(I am not using the javascript sdk).
I have the facebook object.I printed it's methods and tried printint the user id while I was logged into facebook.
This did not work.
My questions are the following:
1)Why does it not work to print the facebook id?
2)What is the most simplest solution to programatically post to my facebook page ?(from my app,or from my user)
What am I doing wrong ?
This is my code
$config = array(
'appId' => 'xxxx',
'secret' => 'xxxx',
'cookie' => true,
);
$this->load->library('facebook', $config);
echo '<pre>';print_r(get_class_methods($this->facebook));
$id = $this->facebook->getAppId();
$secret =$this->facebook->getApiSecret();
$uri = "http://tipsterscorner.com/stats/display/facebook1";//callback_url se pare ca nu e bun
//i build the facebook url.If I use this in the browser ,I get a series of popups(do you allow the application to blabla)
//I read somewhere that if I change the last parametere to code,and use curl,I will get the token in the response
//printed on the screen of the return url,but that does not happen
$facebook_url = "https://www.facebook.com/dialog/oauth?`client_id=$id&client_secret=$secret&redirect_uri=$uri&scope=publish_stream,offline_access,read_stream,manage_pages&response_type=token";`
$curl = curl_init();
// Set some options - we are passing in a useragent too here
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $facebook_url,
CURLOPT_USERAGENT => 'Codular Sample cURL Request'
));
// Send the request & save response to $resp
$resp = curl_exec($curl);
This is the url.
http://tipsterscorner.com/stats/display/facebook1
Thank you very much.
To post on facebook by yourself and on behalf of other's using the app you need to obtain user access token. There are two kinds of Access Tokens namely App Access Token and User Access Token. When app is posting on user's behalf User Access Token is required. User Access Token is generated when a User gives permissions for the app(The dialog popup which you experienced when entering the facebook url in browser). Its solely upon user whether or not to grant permission to the app to post on their behalf. App should be developed to handle both the situations. Once User have given permission(Basic Permission which includes all publicly available info of the user), user access token will be generated. You can either store it in database table or in SESSION. Sometimes user access tokens may become invalid and new token has to be retrieved. During that time curl can be used to retrieve because user has already granted permission for the app.
http://developers.facebook.com/blog/post/2011/05/13/how-to--handle-expired-access-tokens/

Categories