How would you perform `debug_token` call using facebook php sdk? - php

According to the documentation the endpoint looks like
GET /debug_token?
input_token={input-token}&
access_token={access-token}
where
input_token: the access token you want to get information about
access_token: your app access token or a valid user access token from a developer of the app
Assuming I don't have a "valid user access token from a developer of the app" - just because I don't want to refresh it every 2 months and keep always it in mind - how would I perform it using "app access token"?
The getApplicationAccessToken() method is protected, so there is no way to access it without overriding it to public.
Any elegant solution that I'm missing?
PS: a call example that would fail with "You must provide an app access token or a user access token that is an owner or developer of the app" error due to lack of access token:
$tokenDebug = $fb->api('debug_token', array(
'input_token' => $token,
));
PPS: the "interesting" thing is that the error from above would appear not for every $token but for some, and I cannot see any obvious distinction between tokens that fail and that succeed.
PPPS: $token is a user access token
PPPPS: Created a feature request for FB PHP SDK https://developers.facebook.com/bugs/637897982899835
PPPPPS: Probably it could be better to create a pull request instead, but it's 1:30am and I'm too tired for that

OK, so if one needs an app access token, app_id|app_secret (both values concatenated with a pipe symbol in the middle) always works.
The method getApplicationAccessToken seems to have been protected in the PHP SDK up to 3.2.2 – whereas getAppId and getAppSecret are already public in that version; so those could be the alternative to hard-coding id and secret in place.

The PHP SDK has the getOAuth2Client() client method, that returns a \Facebook\Authentication\OAuth2Client instance.
This has the debugToken($accessToken) method, that returns a \Facebook\Authentication\AccessTokenMetadata instance that contains data about the access token.
$appid = '123456789';
$appsecret = 'foobar';
$api = new Facebook(['app_id' => $appid, 'app_secret' => $appsecret]);
$oauth = $api->getOAuth2Client();
$meta = $oauth->debugToken($accessToken);
$meta->validateAppId($appid); // Will throw a FacebookSDKException if invalid
$meta->getIsValid(); // boolean
$meta->getExpiresAt(); // \DateTime|null

Related

amplify federatedSignIn returns accessToken without scopes

I'm trying to use amplify for my Vue app but I have some issues.
When I authenticate manually via Auth.signIn, all goes fine, I get the access token, I pass it to my backend and get the data I want.
But I wanted to save time by not having to build the flows of reset, confirm, forget password, then I tried to use Auth.federatedSignIn
When I do this, the auth works fine as well, but when I pass the accessToken I got to the backend, ie complains the following:
Access Token does not have required scopes
Error executing "GetUser" on "https://cognito-idp.eu-central-1.amazonaws.com"; AWS HTTP error: Client error: `POST https://cognito-idp.eu-central-1.amazonaws.com` resulted in a `400 Bad Request` response:
{"__type":"NotAuthorizedException","message":"Access Token does not have required scopes"}
NotAuthorizedException (client): Access Token does not have required scopes - {"__type":"NotAuthorizedException","message":"Access Token does not have required scopes"}
How do I call Auth.federatedSignIn() and make my token have these scopes exactly as the Auth.signIn()? Is there an additional argument I have to add?
I don't think it's my PHP/aws-sdk authorisation part, since it works when I pass the token obtained via the Auth.signIn()
Here is my current arguments for the amplify Amplify.configure()
export default {
region: process.env.VUE_APP_AWS_DEFAULT_REGION,
userPoolId: process.env.VUE_APP_COGNITO_USER_POOL_ID,
userPoolWebClientId: process.env.VUE_APP_COGNITO_WEB_CLIENT_ID,
oauth: {
domain: process.env.VUE_APP_COGNITO_OAUTH_DOMAIN,
scope: ['email', 'openid'],
redirectSignIn: process.env.VUE_APP_BASE_URL,
redirectSignOut: process.env.VUE_APP_BASE_URL,
responseType: 'code'
}
}
Auth.signIn() and Auth.federatedSignIn() return different things, you can look into source for Auth Amplify in Github to see.
Basically federatedSignIn return credentials and attributes from Attribute mapping while signIn return a Cognito user, token, session, ...
So asking Auth.federatedSignIn() to return the same as Auth.signIn() is impossible no matter how you try to configure it.

Retrieving facebook user access token with socialite on laravel 5.4

I am trying to get user access token so I can send CURL request through Guzzle to Facebook's Graph API to get user's friends that are using the app. But I can't seem to be able to obtain it.
Here's my controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Client;
use Socialite;
class SocialFriendsController extends Controller
{
public function getFacebookFriends()
{
$user = Socialite::driver('facebook')->user();
$access_token = $user->token;
$client = new Client();
$body = $client->get('https://graph.facebook.com/v2.11/me/friends', [
'query' => [
'access_token' => '$access_token',
]
])->getBody();
$result = \GuzzleHttp\json_decode($body, 1);
return view('pages.admin.posts.create', ['result' => $result]);
}
}
Once you have followed the previous answer to fix the reference to $access_token you can do the following steps with the facebook SDK to retrieve a long lived token from Facebook so you can make many calls to the API. The default auth token will work for 2 hours after which you will need to re-initiate the oAuth flow to get a new token. A long lived token gets you 2 months of access before having to do the oAuth again.
https://developers.facebook.com/docs/facebook-login/access-tokens/expiration-and-extension
$facebook = new \Facebook\Facebook();
$client = $facebook->getOAuth2Client();
$twoMonthToken = $client->getLongLivedAccessToken($twoHourToken);
Update the user with the $twoMonthToken
A couple of things to note. First of all, the following part of your code won't work the way you expect it to:
'access_token' => '$access_token',
You're trying to do variable interpolation, which doesn't work when you use single quotes ('). You should use double quotes ("$access_token") instead, or since you're not actually doing anything else with that string, you could just remove the quotes altogether.
Secondly, when doing Facebook logins (In your case, using Socialite) the access token you receive from Facebook is single use (I think so anyway - at least from my own experience). When you do Socialite::driver('facebook')->user(), Socialite is actually using the access token to grab the user object. If you attempt to use it again, Facebook will return an error.
Socialite is probably not the way to go to achieve what you're trying to do. I would suggest using the Facebook SDK directly to get what you're after.
$user = Socialite::driver('facebook')->userFromToken($access_token);
You can simply pass your access_token like above that will return user info.

Twitter API responds with "Your credentials do not allow access to this resource" while calling statuses/update.json

I'm using Hybridauth 3 in my PHP app to make some periodical tweets on behalf of my account.
The app has all possible permissions. I'm giving it all permissions when it asks for them on the first auth step.
After that Twitter redirects me to the specified callback URL and there I'm getting a pair of access_token and access_token_secret.
But when I'm trying to make a tweet using these tokens - it gives me:
{"errors":[{"code":220,"message":"Your credentials do not allow access to this resource."}]}
Here's how I'm trying to make a tweet:
$config = [
'authentication_parameters' => [
//Location where to redirect users once they authenticate
'callback' => 'https://mysite/twittercallback/',
//Twitter application credentials
'keys' => [
'key' => 'xxx',
'secret' => 'yyy'
],
'authorize' => true
]
];
$adapter = new Hybridauth\Provider\Twitter($config['authentication_parameters']);
//Attempt to authenticate the user
$adapter->setAccessToken(/*tokens I've got from getAccessToken() on /twittercallback/*/);
if(! $adapter->isConnected()) {
// never goes here, so adapter is connected
return null;
}
try{
$response = $adapter->setUserStatus('Hello world!');
}
catch (\Exception $e) {
// here I've got the error
echo $e->getMessage();
return;
}
Tried to recreate tokens and key\secret pairs and passed auth process for the app many times, including entering password for my Twitter account (as suggested in some posts on stackoverflow) but still have this error.
P.S. According to this, Hybridauth has fixed the issue in the recent release.
It looks like you are using application authentication as opposed to user authentication. In order to post a tweet, you must authenticate as a user. Also, make sure your Twitter app has read/write privileges.
After comparing headers of outgoing requests from my server with the ones required by Twitter, I've noticed that Hybris doesn't add very important part of the header: oauth_token. At least it's not doing this in the code for Twitter adapter and for the scenario when you apply access token with setAccessToken(). It's just storing tokens in the inner storage but not initializing corresponding class member called consumerToken in OAuth1 class.
So to initialize the consumer token properly I've overridden the apiRequest method for Twitter class (before it used the defalut parent implementation) and added a small condition, so when consumer token is empty before the request - we need to try to init it.
public function apiRequest($url, $method = 'GET', $parameters = [], $headers = [])
{
if(empty($this->consumerToken)) {
$this->initialize();
}
return parent::apiRequest($url, $method, $parameters, $headers);
}
I'm not sure that I've fixed it the best way, but as long as it's working - that's fine.
For your info setAccessToken was fixed in v3.0.0-beta.2 (see PR https://github.com/hybridauth/hybridauth/pull/880)
I faced the same error when implementing a sample app in clojure and the following resource was a huge help to sort out my confusion about application-only auth vs user authentication: https://developer.twitter.com/en/docs/basics/authentication/overview/oauth

Marketing Api Permission Exception

I need to get some automated ad insights using the Marketing Api. For this purpose I have created a System User via the Business Manager, and generated a System User access token with the ads_read permission.
Using this token then to make api calls and get a specific Campaign's Insights, with the FacebookAds php v2.6 sdk, I get the following error:
Uncaught exception 'FacebookAds\Http\Exception\PermissionException'
with message '(#275) Cannot determine the target object for this
request. Currently supported objects include ad account, business
account and associated objects.'
Does my app need to be whitelisted or am I missing something else? I noticed that next to the 'ads_read' permission there was this note that stated '(your App must be whitelisted)'.
Here is the sample code I'm using
<?php
define('VENDOR_DIR', 'vendor/'); // Path to the Vendor directory
$loader = require VENDOR_DIR.'autoload.php';
use FacebookAds\Api;
use FacebookAds\Object\Campaign;
// Initialize a new Session and instantiate an Api object
Api::init(
'xxxxxxxxxxxxxxxx', // App ID
'xxxxxxxxxxxxxxxxx',
'xxxxxxxxxxxxxxxxxx' // System User Access Token
);
$api = Api::instance();
use FacebookAds\Object\Values\InsightsLevels;
$campaign = new Campaign('xxxxxxxxxxxxx');
$params = array(
'level' => InsightsLevels::CAMPAIGN,
);
$async_job = $campaign->getInsightsAsync(array(), $params);
$async_job->read();
while (!$async_job->isComplete()) {
sleep(1);
$async_job->read();
}
$async_job->getResult();
?>
It seems like your app doesn't have ads_read permission. Here you can find more information on how to ask for it: https://developers.facebook.com/docs/marketing-api/access

Why is my Facebook access_token shorter than the example and missing the 'session part'?

I'm designing a Facebook app and trying to obtain the "location" of my friends. Using the Graph API explorer tool: http://developers.facebook.com/tools/explorer/ it's a snap.
However, when I make the call to get the access token, from a authenticated App user, the token I receive is shorter than the token generated from the Graph API explorer tool. This shortened token allows me to receive basic friend information but does not allow me to retrieve the location object. Doing some research seems to indicate that I am missing the 'session part' of the token http://benbiddington.wordpress.com/2010/04/23/facebook-graph-api-getting-access-tokens/
How am I able to retrieve this 'session part?' Why is the token I receive from Facebook not the same token I receive from the Graph Explorer API?
Note: I made sure I'm requesting the necessary extended permissions to read my friends location.
Make sure you have a user access_token. If you are using the PHP-SDK, then most likely you are using the app access_token.
The SDK will always get the app access_token and use it if no user access_token is present (reference):
/**
* Determines the access token that should be used for API calls.
* The first time this is called, $this->accessToken is set equal
* to either a valid user access token, or it's set to the application
* access token if a valid user access token wasn't available. Subsequent
* calls return whatever the first call returned.
*
* #return string The access token
*/
public function getAccessToken() {
if ($this->accessToken !== null) {
// we've done this already and cached it. Just return.
return $this->accessToken;
}
// first establish access token to be the application
// access token, in case we navigate to the /oauth/access_token
// endpoint, where SOME access token is required.
$this->setAccessToken($this->getApplicationAccessToken());
$user_access_token = $this->getUserAccessToken();
if ($user_access_token) {
$this->setAccessToken($user_access_token);
}
return $this->accessToken;
}

Categories