Twitter reverse authentication with PHP - php

I am trying to set up twitter reverse auth, on my api server. My mobile device will call this api endpoint to get the request token, and use that to sign-in using twitter, and do different actions on the hand-held device.
I am using j7mbo/twitter-api-php: Simplest PHP example for retrieving user_timeline with Twitter API version 1.1
This lib has just a basic post and get examples, but I looked into the source and found the buildOauth to doing everything that is required for twitter i.e. generate the signature base string and authorization header, and it calling the endpoint using curl.
In my code I set my consumer_key, secret, access_token key and secret, and set the x_auth_mode like below:
$tw_settings = array(
'consumer_key' => $app['config']['twitter_api']['consumer_key'][$culture],
'consumer_secret' => $app['config']['twitter_api']['consumer_secret'][$culture],
'oauth_access_token' => $app['config']['twitter_api']['api_access_token'][$culture],
'oauth_access_token_secret' => $app['config']['twitter_api']['api_access_token_secret'][$culture],
);
$postfields = array(
'x_auth_mode' => 'reverse_auth'
);
$twitter = new TwitterAPIExchange($tw_settings);
$result = $twitter->setPostFields($postfields)
->buildOauth($url, $requestMethod)
->performRequest();
return $app->json($result);
But twitter does not authenticate, saying "Failed to authenticate oauth signature and token".

I finally got it working. You can get this git repo based on j7mbo/twitter-php-api. I have extended to add a method to get reverse auth token from twitter. This token you can generate on your server, and expose it using an rest endpoint, which your device will call, and use it to do reverse authentication. This way the consumer-key and consumer secret is safe tucked away on the server and is not distributed with all the client devices.
Git repo: https://github.com/srinivasmangipudi/twitter-api-php
To generate the special request token, instantiate the TwitterApiExcahange object and then call 'buildReverseOauth' method. E.g:
$postfields = array(
'x_auth_mode' => 'reverse_auth'
);
$twitter = new TwitterAPIExchange($tw_settings);
$result = $twitter->setPostfields($postfields)
->buildReverseOauth($url, $requestMethod)
->performRequest();
This should return you the oauth_access_token. Rest everything is same as below.

Related

How to make a call with the Twitter V2 API

I'm using the below code to search Tweets with the query parameter. This works fine with the Twitter V1 API, but not with the V2, and after extensively reading their API documentation, I'm confused.
My first question is, do the V1 and V2 share the same authentication? i.e. can I make a call to the V2 with this code, assuming my end point url is correct which leads to the second question, if I can make a call to the V2 with the same auth as the V1, what's the correct end point? the notable differences so far is the query parameter which is "q" for the V1 and "query" for the V2. Then apparently the .json is not needed, but I tried both at the end of the V2 end point and still I get the same error:
stdClass Object ( [client_id] => 131XXXXXX [detail] => When authenticating requests to the Twitter API v2 endpoints, you must use keys and tokens from a Twitter developer App that is attached to a Project. You can create a project via the developer portal. [registration_url] => https://developer.twitter.com/en/docs/projects/overview [title] => Client Forbidden [required_enrollment] => Standard Basic [reason] => client-not-enrolled [type] => https://api.twitter.com/2/problems/client-forbidden )
include ($_SERVER["DOCUMENT_ROOT"] . "/TwitterAPIExchange.php");
$settings = array(
'oauth_access_token' => "xxx",
'oauth_access_token_secret' => "xxx",
'consumer_key' => "xxx",
'consumer_secret' => "xxx"
);
//$url = "https://api.twitter.com/1.1/search/tweets.json";
$url = "https://api.twitter.com/2/tweets/search/recent";
$requestMethod = "GET";
// V1
//$getfield = '?q=bitcoin';
// V2
$getfield = '?query=bitcoin';
$twitter = new TwitterAPIExchange($settings);
$response = $twitter->setGetfield($getfield)
->buildOauth($url, $requestMethod)
->performRequest();
$tweets = json_decode($response);
print_r($tweets);
EDIT:
Looks like the V1 and V2 can share the same auth: https://developer.twitter.com/en/docs/twitter-api/tweets/search/migrate/standard-to-twitter-api-v2
OAuth 1.0a User Context and OAuth 2.0 Bearer Token authentication
The v1.1 search/tweets and the Twitter API v2 recent search endpoint support both OAuth 1.0a User Context and OAuth 2.0 Bearer Token.
Therefore, if you were previously using the standard v1.1 search endpoint you can continue using the same authentication method if you migrate to the Twitter API v2 version.
First you have to add the app you’re using to a “Project” on the Developer dashboard. This step is necessary to be able to call v2 endpoints see: https://developer.twitter.com/en/docs/projects/overview
I got this answer from the twitter community forum and now it works fine with the code posted in my question above.

Twitter webhook registration error | {"errors":[{"code":32,"message":"Could not authenticate you."}]}

when I try to register the twitter web-hook, api returns the error message "Could not authenticate you".
I am using the below php wrapper for twitter api v1.1.
twitter-api-php
$settings = array(
'oauth_access_token' => $accesstoken,
'oauth_access_token_secret' => $accesstokensecret,
'consumer_key' => $consumerkey,
'consumer_secret' => $consumersecret
);
$url = 'https://api.twitter.com/1.1/account_activity/all/msgdev/webhooks.json?url=https://myapp.com/twitterwebhook.php';
$requestMethod = 'POST';
$twitter = new TwitterAPIExchange($settings);
echo $twitter->buildOauth($url, $requestMethod)->performRequest();
I am able to send message. But not able to create webhook.
Created developer account and got api access, also created twitter app in apps.twitter.com
You can fix this issue by doing a url-encode on your URL parameter. Refer the sample code on how we are doing it in ruby.
response = #twitter_api.post('https://api.twitter.com/1.1/account_activity/all/chatwootdev/webhooks.json?url=https%3A%2F%2Fchatwoot.com%2F16b66d68-c9f9-4c2e-8caa-4244cff8b483', nil, HEADERS)
Also note that you will need to implement a CRC check at your webhook url before you start getting the events from twitter. If the CRC is not implemented. you will be recieveing 214 error code.
ref: getting started with twitter accounts subscription api

How to get RSS token for BitBucket by PHP CLI?

I want to get valid link https://bitbucket.org/{username}/rss/feed?token={token} (this is main problem) and then get valid response from this link in CLI.
I know my required parameters, e.g. consumer_key, consumer_secret, request_token_url, authenticate_url, access_token_url.
I tried to use StudioIbizz\OAuth\OAuth1, but is seems to be designed for Browser, not for CLI.
I tried to run:
$this->OAuth = new \StudioIbizz\OAuth\OAuth1($this->consumer_key,$this->consumer_secret);
$requestToken = $this->OAuth->getRequestToken($this->request_token_url,$this->authenticate_url);
$token = $requestToken['oauth_token_secret'];
and paste this $token to my RSS link, but then I see message You must have read access to access the RSS feed. from Bitbucket.
I need Step by Step instructions for serious dummies.
Edit: I tried this:
$accessToken = $this->OAuth->getAccessToken($this->access_token_url,$requestToken['oauth_token_secret'],$requestToken['oauth_token']);
But then I get this:
Fatal error: Uncaught exception 'StudioIbizz\OAuth\OAuthException' with message 'Unexpected HTTP status #400'
I don't see any function related with that on official documentation. Maybe that feature not exists.
For more information, you could use this link:
https://confluence.atlassian.com/bitbucket/use-the-bitbucket-cloud-rest-apis-222724129.html
You could use stevenmaguire's Bitbucket OAuth 2.0 support for the PHP League's OAuth 2.0 Client.
$provider = new Stevenmaguire\OAuth2\Client\Provider\Bitbucket([
'clientId' => '{bitbucket-client-id}',
'clientSecret' => '{bitbucket-client-secret}',
'redirectUri' => 'https://example.com/callback-url'
]);
$token = $_GET['code'];
To get an RSS token for Bitbucket via PHP CLI, you will need to use the OAuth 1.0a protocol to authenticate your request. Here are the steps you can follow:
Install an OAuth library for PHP that can be used in CLI, such as the league/oauth1-client package.
Create a new instance of the OAuth client by passing in your consumer key and consumer secret.
$client = new League\OAuth1\Client\Server\Bitbucket($consumerKey, $consumerSecret);
Get the request token by calling the getTemporaryCredentials method and passing in the callback URL.
$temporaryCredentials = $client->getTemporaryCredentials();
Get the authorization URL by calling the getAuthorizationUrl method and passing in the temporary credentials.
$authorizationUrl = $client->getAuthorizationUrl($temporaryCredentials);
Use this URL to authenticate the request via the browser.
After successful authentication, you will get a verifier code.
Get the access token by calling the getTokenCredentials method and passing in the temporary credentials and the verifier code.
$tokenCredentials = $client->getTokenCredentials($temporaryCredentials, $verifier);
$tokenCredentials = $client->getTokenCredentials($temporaryCredentials, $verifier);
Get the RSS token by calling the getRssToken method and passing in the token credentials
$rssToken = $client->getRssToken($tokenCredentials);
You can use this token to construct your RSS feed link:
https://bitbucket.org/{username}/rss/feed?token={$rssToken}
Note that, this is just a general idea of how to use the OAuth library and it may vary depending on the library you are using. It's also important to check the documentation of that library for more details.

How to keep OAuth settings a secret?

After creating my Twitter application, the following warning was displayed:
OAuth settings
Your application's OAuth settings. Keep the "Consumer secret" a
secret. This key should never be human-readable in your application.
How do I keep my "Consumer Secret" a secret?
Twitter_test.php (source: Jimbo)
// Set access tokens here
$settings = array(
'oauth_access_token' => "My Oauth Access Token",
'oauth_access_token_secret' => "My Oauth Access Token Secret",
'consumer_key' => "My Consumer Key",
'consumer_secret' => "My Consumer Secret"
);
$url = 'https://api.twitter.com/1.1/followers/ids.json';
$getfield = '?username=somename';
$requestMethod = 'GET';
$twitter = new TwitterAPIExchange($settings);
echo $twitter->setGetfield($getfield)
->buildOauth($url, $requestMethod)
->performRequest();
?>
TwitterAPIExchange (source: twitter-api-php)
I'd create a library integrated with the Twitter Api, and store the data in a config file in application/config/ as mentioned in given link.
To please Twitter, simply parse:
$this->load->library('encrypt');
echo $this->encrypt->encode('your given secret here');
Take the output, store it inside the config file, and when you're fetching it:
$this->load->library('encrypt');
$str_secret = $this->encrypt->decode($config['secret']);
Encryption
-Don't forget to set a key as described in this link.
Note that they demand you to do that for maximum security, in case someone would get control over your ftp or similiar. However if it can be decoded, it can be read. This isn't the ultimate solution, but simply a bit more reliable one.
You can save Consumer secret in database in serialize format and than unserialize while fetching and than use it.
consumer_secret is a secret key given by twitter when you sign up for the apis. You can keep it safe by putting twitter code in your library or any as such folder and make sure that folder is not directly accessible using browser url.
For example if you put twitter config.php in lib folder then it should not be accessible like this
www.somedomain.com/lib/config.php

Google Calendar API v3 - authenticate with hardcoded credentials

I am writing a PHP application that's supposed to allow users to add certain events to a private Google Calendar. The calendar is owned by me, and I need a way for PHP to communicate with the calendar API using fixed credentials (everyone can add events using a form on the website, but the calendar itself is not publicly visible).
From what I have read, this is possible using ClientLogin in the v1 API. In the v3 API, however, the available options are OAuth2.0 or the API key. Using the API key doesn't seem to work, since it can only be used for requests that don't require authorization, and OAuth doesn't seem right either, because users are not supposed to access their own calendars, but the one my application uses.
I thought about getting the OAuth token programatically, but that's bound to break sooner or later, since the OAuth dialog can use captchas.
This seems to be such a standard use case — a web application that lets users interact with a single calendar in some predefined ways — yet I can't find any documentation on how to make it happen in the v3 API. Can anyone help me?
I have found a solution that I think that is "the official" for what you want to do.
First, you have to activate a Google API "Client ID for installed applications".
Go to the Google API console and create the project.
Then, activate the calendar.
Go to the "API access" option, and use the "Create OAuth 2.0 client" button.
Give a name (and a logo, if you want) to the product. Click "next".
Choose the "Installed application" option and click "Create Client Id".
Now you have your access configurated. Now, you will need some codes. To obtain them:
*The "Authentication Code". To get it, you need the following information:
SCOPE: https://www.google.com/calendar/feeds/ (if you want to access the calendar API. There are others you can find them at the OAuth 2.0 Playground)
CLIENT_ID: You will find it at the API Access Section at the Google API Console.
REDIRECT_URI: Get it at the same place.
Now, copy the following code into a file, put the values into the variables, execute the code (php -q script_name.php), and go to the URL printed.
<?php
$scope = '';
$client_id = '';
$redirect_uri = '';
$params = array(
'response_type' => 'code',
'client_id' => $client_id,
'redirect_uri' => $redirect_uri,
'scope' => $scope
);
$url = 'https://accounts.google.com/o/oauth2/auth?' . http_build_query($params);
echo $url."\n";
?>
The web page will ask you to allow the access. Do it, and you will get a code, which is your Authentication Code.
*The "Refresh Code". To get it, you will need:
The data you used before, plus the "client secret" code in the API Console, between the "client id" and the "redirect URI".
As you did before, copy the following code, and put the variables in place (the code field is the Authentication Code).
Execute and the result is the "Refresh Token".
<?php
$url = 'https://accounts.google.com/o/oauth2/token';
$post_data = array(
'code' => '',
'client_id' => '',
'client_secret' => '',
'redirect_uri' => '',
'grant_type' => 'authorization_code',
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$token = json_decode($result);
echo $token->refresh_token . "\n";
?>
At this moment, you have all you need. Be careful if one day you change the Authentication Code. You will have to get new keys.
To access a calendar service, here you have the example:
Change the variable values before using it.
This example gets the primary calendar events, but you can change the address for any in the calendar API (http://code.google.com/intl/ca/apis/calendar/v3/getting_started.html#background_operations)
<?php
$scope = 'https://www.google.com/calendar/feeds/';
$client_id = '';
$client_secret = '';
$redirect_uri = '';
$refresh_token = '';
$token_url = 'https://accounts.google.com/o/oauth2/token';
$post_data = array(
'client_secret' => $client_secret,
'grant_type' => 'refresh_token',
'refresh_token' => $refresh_token,
'client_id' => $client_id
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $token_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$token_object = json_decode($result);
$access_token = $token_object->access_token;
// Get the results
$rest_url = 'https://www.googleapis.com/calendar/v3/calendars/primary/events';
$header = "Authorization: OAuth " . $access_token;
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, array($header));
curl_setopt($ch, CURLOPT_URL, $rest_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$rest_result = curl_exec($ch);
print_r(json_decode($rest_result));
?>
First, the script asks for an "Access Token", which is valid for an hour. Then, the script gets the REST service (any in the calendar scope), sending the access token in the header.
To give a best speed at the scrip, it would be good to store the access token in a cache until it's older than 3600 seconds. This way, the script would avoid one of the two calls.
Tips:
Visit OAuth 2.0 Playground to understand all the information sent in the OAuth process. It helped me a lot
A post by Eric Nagel in his blog gave me the solution. All the merit is to him. I can't link it since I haven't got enough "reputation".
You will need to use both the Developer Key (API Key) and OAuth2. The developer key authenticates who wrote the software and is used for things like quota which is on a per developer basis not a per user basis. OAuth2 is for user authentication and will be need to access the non-public calendar.
OAuth2 has a renew token from which you can generate a session token and this means that you will not need to screen scrape the OAuth screens to get authenticated. To get this I would write a little command line application, or you use a one off PHP page.
Under the Google Api Console go to API Access
Generate a new Client ID and choose Installed Application ( as you will be authenticating you server as you not as your user)
Either using a console app or a one off PHP page authenticate using OAuth and your google account (the one with the calendar you want access to)
In the return from the authentication there should be a renew token, (called renew or refresh or something similar). Save this string and make it available to your PHP site.
When you need to access the service your OAuth library should have a renew/refresh call. There is an example using .Net below.
private IAuthorizationState CreateAuthorization(NativeApplicationClient arg)
{
// Get the auth URL:
IAuthorizationState state = new AuthorizationState(new[] { AdsenseService.Scopes.AdsenseReadonly.GetStringValue() });
state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
if (refreshToken.IsNotNullOrEmpty()) // refreshToken you stored in step 4
{
try
{
state.RefreshToken = refreshToken;
if (arg.RefreshToken(state)) // This is calling out to the OAuth servers with the refresh token getting back a session token, returns true if successful.
{
if (state.RefreshToken != refreshToken) // if the refresh token has changed, save it.
{
PersistRefreshToken(authorization.RefreshToken);
}
return this.authorization = state; // Retain the authorization state, this is what will authenticate your calls.
}
}
catch (ProtocolException ex) {...}
The AuthorisationState that has now been renewed can then be used to authenticate call you make to the API. this state can be used many time until it expires and then can be refreshed. As you are authenticating your application as yourself not as a user this AuthorisationState can be shared by all you sessions. Both the current AuthorisationState and the refresh token should be kept securely on your server and never sent to the client, if you ever sent these as part of a response your clients would have the same privileges as your code application
Can also be used with the Google php library. The access token for the $client->setAccessToken() function has to be formatted in the following way:
$at= '{"access_token":"' . $access_token . '",' .
'"token_type":"Bearer",' .
'"expires_in":3600,' .
'"refresh_token":"' . $refresh_token . '",',
'"created":' . time() . '}';
Where $access_token is the access token found by you and $refresh_token is the refresh token. Tested with the useless simple.php google example.
Authentication is then just:
$client->setAccessToken($at);

Categories