Issues using pubnub access manager to publish with php - php

I am trying to use pubnub with their access manager to authorize certain users to a specific channel and then publish a message to the channel after the user has been granted read/write rights. I must be doing something wrong with the publish() call on this after granting access to the user. The first part of code below returns what looks like a successful response for the grant() but the publish() call results in :
Fatal error: Call to undefined method access::publish() in /home/dayfv98/public_html/mobile/pubtest.php on line 48
Here is my code:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
require('pubnub.php');
require('pam.php');
$chat_entry = addslashes(trim($_POST['chat_entry']));
// CONNECT TO ACCESS MANAGER
$manager = new access(
"MY_PUB_KEY...not included for security",
"MY_SUB_KEY...not included for security",
"MY_SEC_KEY...not included for security"
);
## Grant User Access
print_r($manager->grant(
"chat", // CHANNEL
"44444", // STRING (AUTH KEY)
true, // READ
true, // WRITE
0 // TTL in MINUTES
));
$manager->publish(array(
'channel' => 'chat', ## REQUIRED Channel to Send
'message' => $chat_entry
));
?>

The access manager library is not intended to be used to do anything outside of the scope of the access manager. It is only intended for grants, revokes, and audits.
You will need to use the normal PubNub sdk, but when constructing your PubNub object, provide the auth token you have previously granted.
**EDIT : ** The PHP SDK seems to have some issue with Access Manager right now. I've done some minor hotfix modifications to address this and have included them into a gist, but please keep an eye on the official repository on github for a newer version : https://gist.github.com/keyosk/9c86b981948a3cf7f378
For instance, to use the auth token you granted in your example above, you would do this :
$pubnub = new Pubnub(array(
'publish_key' => 'MY_PUB_KEY',
'subscribe_key' => 'MY_SUB_KEY',
'auth_token' => '44444',
));
$pubnub->publish(array(
'channel' => 'chat',
'message' => $chat_entry
));

Related

GET User returns Authorization_IdentityNotFound error

I'm building an application that has a simple email-pass login. I want to use the Microsoft Graph to return the profile information of a user that has logged in (I'm not using office365 OAuth right now).
I've set up an action that tries to fetch this user data (i.e given name or profile photo) from an organization I'm part of. I got this error:
"line":113,
"message":"Client error: GET https://graph.microsoft.com/v1.0/users/{user}
resulted in a 401 Unauthorized response:
{
"error": {
"code": "Authorization_IdentityNotFound",
"message": "The identity of the calling application (truncated...)"
}
}
I've set up the application as specified on the Microsoft Graph tutorial (step 2) and this the code I've written, using the repository readme:
class MsGraphService implements iAction
{
protected $accessToken;
public function __construct()
{
$guzzle = new \GuzzleHttp\Client();
$url = 'https://login.microsoftonline.com/'.ENV('MSGRAPH_TENAND_ID').'/oauth2/token?api-version=1.0';
$token = json_decode($guzzle->post($url, [
'form_params' => [
'client_id' => ENV('MSGRAPH_CLIENT_ID'),
'client_secret' => ENV('MSGRAHP_CLIENT_SECRET'),
'resource' => 'https://graph.microsoft.com/',
'grant_type' => 'client_credentials',
],
])->getBody()->getContents());
$this->accessToken = $token->access_token;
}
public function execute($data)
{
$graph = new Graph();
$graph->setAccessToken($this->accessToken);
$user = $graph->createRequest("GET", sprintf("/users/%s",$data['email']))
->setReturnType(Model\User::class)
->execute();
return $user->getGivenName();
}
}
The accesstoken attribute was caught, so I think the app configuration is ok.
Maybe is an issue about API permissions, specifically: Application permissions?
I've also asked about this on GitHub.
You are probably running into problems because you are trying to use the AzureAD V1 authentication endpoint. It is much easier to get the AzureAD v2 endpoint to work with Microsoft Graph. There are details on how to do it here https://learn.microsoft.com/en-us/graph/tutorials/php?tutorial-step=3
The main different between V1 and V2 is that you no longer use a resource parameter and you use scopes instead to say want you want access to.
When trying to fetch user related information using the API (no signed-in user) you should ask an administrator for permissions to read that information. In order to set the correct permissions to your application you should:
Go to https://portal.azure.com and login
Click on Azure Active Directory
Go to App Registrations
Select your existing appliaction and click on View API permissions
Select + Add a permission / Microsoft Graph / Application Permissions / User / User.Read.All
Ask an administrator for consent
With that, you will be able to fetch users data from your application without a signed-in user.

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

PHP SDK Cannot get AWS Credentials on EC2 Instance with IAM Role attached

Simple question. But cannot get it to work.
I created an IAM Role for EC2 with full access to CloudWatch.
I launched a new EC2 instance with this IAM Role attached.
I wrote a simple PHP application on this EC2 instance which tries to publish metrics to CloudWatch.
I am getting this error in nginx logs:
2017/08/23 11:44:06 [error] 32142#32142: *5 FastCGI sent in stderr:
"PHP message: PHP Fatal error:
Uncaught Aws\Exception\CredentialsException:
Cannot read credentials from /var/www/.aws/credentials
in /var/www/app/vendor/aws/aws-sdk-php/src/Credentials/CredentialProvider.php:394
From that same EC2 instance, the command:
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-attached-to-ec2-instance>
returns 200 OK with the Access Key and Secret in the response.
This is my PHP code that tries to write CloudWatch metrics:
<?php
require 'vendor/autoload.php';
use Aws\CloudWatch\CloudWatchClient;
use Aws\Exception\AwsException;
$count = $_GET["count"];
publishMetric($count);
function publishMetric($count) {
$client = new CloudWatchClient([
'profile' => 'default',
'region' => 'us-east-1',
'version' => '2010-08-01'
]);
try {
$result = $client->putMetricData(array(
'Namespace' => 'com.mynamespace',
'MetricData' => array(
array(
'MetricName' => 'Count',
//Timestamp : mixed type: string (date format)|int (unix timestamp)|\DateTime
'Timestamp' => time(),
'Value' => $count,
'Unit' => 'Number'
)
)
));
var_dump($result);
echo 'Done publishing metrics';
} catch (AwsException $e) {
// output error message if fails
error_log($e->getMessage());
echo 'Failure to publish metrics';
}
}
?>
Any idea what is missing in this setup?
I know this is late. I had the same issue and resolved it by removing profile => default line while initializing the client. If you do not provide credentials and profile, SDK will try to retrieve instance profile creds from metadata server.
Authentication of EC2 instance while accessing other AWS Services can be done in multiple ways:
Assigning a role to EC2 instance. Used when u have to give some "EC2 instance" a permission.
Do not assign a role; but use access-key which has all required permissions. Used when you give permission to a "User"
Both these are independent authentication mechanism. If you have already assigned role to your server; you do not have to write any code in your application (CredentialProvider.php) to authenticate.
Your current code can also be worked by creating a file /var/www/.aws/credentials which will look something like this:
accessKey=AKIAIB6FA52IMGLREIIB
secretKey=NQjJWKT+WZOUOrQ2Pr/WcRey3PnQFaGMJ8nRoaVU

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

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

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

Categories