Auto Post on Twitter after authentication : getting Invalid access token error - twitter

Here I need to automatically post on Twitter after authentication.
My code
<?php
session_start();
include("twitteroauth.php");
define('CONSUMER_KEY','zubLdCze6Erz9SVNIgG3w');
define('CONSUMER_SECRET','ZnZQ77bNnpBER2aSxTQGEXToAQODz9qEBSAXIdeYw');
define('OAUTH_CALLBACK','http://dev.pubs.positive-dedicated.net/Licensee/addPubEventWeekly.php');
/* Build TwitterOAuth object with client credentials. */
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
/* Get temporary credentials. */
$request_token = $connection->getRequestToken(OAUTH_CALLBACK);
/* Save temporary credentials to session. */
$_SESSION['oauth_token'] = $token = $request_token['oauth_token'];
$_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret'];
switch ($connection->http_code) {
case 200:
/* Build authorize URL and redirect user to Twitter. */
$url = $connection->getAuthorizeURL($token);
header('Location: ' . $url);
break;
default:
/* Show notification if something went wrong. */
echo 'Could not connect to Twitter. Refresh the page or try again later.';
}
?>
and
ksort($_SESSION);
$tweet = new TwitterOAuth('zubLdCze6Erz9SVNIgG3w','ZnZQ77bNnpBER2aSxTQGEXToAQODz9qEBSAXIdeYw',$_SESSION['oauth_token'],$_SESSION['oauth_token_secret']);
print_r($tweet);
$account = $tweet->get('account/verify_credentials');
$message = "This is an example twitter post using PHP";
$postVal = $tweet->post('statuses/update', array('status' => $message));
But here I am getting "Invalid/Expired access token" Error.
I have changed twittreauth.php library file also from 1.0 to 1.1 from here
public $host = "https://api.twitter.com/1.1/";
Please suggest how to fix this

Related

Google API login failed always: back to needing to authorize

I'd like to change my tags of a YouTube video using the YouTube Data API. But I'm already stuck on login:
My page shows the message: You need to authorize access before proceeding. I click on authorize access and select my Google account and then my YouTube channel, I select allow and get redirected to the login message.
The code is directly from the sample files on Github:
<?php
/**
* This sample adds new tags to a YouTube video by:
*
* 1. Retrieving the video resource by calling the "youtube.videos.list" method
* and setting the "id" parameter
* 2. Appending new tags to the video resource's snippet.tags[] list
* 3. Updating the video resource by calling the youtube.videos.update method.
*
* #author Ibrahim Ulukaya
*/
/**
* Library Requirements
*
* 1. Install composer (https://getcomposer.org)
* 2. On the command line, change to this directory (api-samples/php)
* 3. Require the google/apiclient library
* $ composer require google/apiclient:~2.0
*/
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}
require_once __DIR__ . '/vendor/autoload.php';
session_start();
/*
* You can acquire an OAuth 2.0 client ID and client secret from the
* {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
* For more information about using OAuth 2.0 to access Google APIs, please see:
* <https://developers.google.com/youtube/v3/guides/authentication>
* Please ensure that you have enabled the YouTube Data API for your project.
*/
$OAUTH2_CLIENT_ID = 'myID';
$OAUTH2_CLIENT_SECRET = 'mySec';
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION[$tokenSessionKey])) {
$client->setAccessToken($_SESSION[$tokenSessionKey]);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
$htmlBody = '';
try{
// REPLACE this value with the video ID of the video being updated.
$videoId = "Zqt-NvuMKYU";
// Call the API's videos.list method to retrieve the video resource.
$listResponse = $youtube->videos->listVideos("snippet",
array('id' => $videoId));
// If $listResponse is empty, the specified video was not found.
if (empty($listResponse)) {
$htmlBody .= sprintf('<h3>Can\'t find a video with video id: %s</h3>', $videoId);
} else {
// Since the request specified a video ID, the response only
// contains one video resource.
$video = $listResponse[0];
$videoSnippet = $video['snippet'];
$tags = $videoSnippet['tags'];
// Preserve any tags already associated with the video. If the video does
// not have any tags, create a new list. Replace the values "tag1" and
// "tag2" with the new tags you want to associate with the video.
if (is_null($tags)) {
$tags = array("tag1", "tag2");
} else {
array_push($tags, "tag1", "tag2");
}
// Set the tags array for the video snippet
$videoSnippet['tags'] = $tags;
// Update the video resource by calling the videos.update() method.
$updateResponse = $youtube->videos->update("snippet", $video);
$responseTags = $updateResponse['snippet']['tags'];
$htmlBody .= "<h3>Video Updated</h3><ul>";
$htmlBody .= sprintf('<li>Tags "%s" and "%s" added for video %s (%s) </li>',
array_pop($responseTags), array_pop($responseTags),
$videoId, $video['snippet']['title']);
$htmlBody .= '</ul>';
}
} catch (Google_Service_Exception $e) {
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'REPLACE_ME') {
$htmlBody = <<<END
<h3>Client Credentials Required</h3>
<p>
You need to set <code>\$OAUTH2_CLIENT_ID</code> and
<code>\$OAUTH2_CLIENT_ID</code> before proceeding.
<p>
END;
} else {
// If the user hasn't authorized the app, initiate the OAuth flow
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to authorize access before proceeding.<p>
END;
}
?>
<!doctype html>
<html>
<head>
<title>Video Updated</title>
</head>
<body>
<?=$htmlBody?>
</body>
</html>
Would be great if someone has a tip for me.
Fixed... was a space key inside secret

500 backend error while inserting YouTube Channel Art

Although, we'd prepared YouTube channel art upload mechanism as described on the it's official documentation page, (https://developers.google.com/youtube/v3/docs/channelBanners/insert), from few days, we are facing following error,
A service error occurred: { "error": { "errors": [ { "domain": "global", "reason": "backendError", "message": "Backend Error" } ], "code": 500, "message": "Backend Error" } }
Which was perfectly working before.
/**
* This sample sets a custom banner for a user's channel by:
*
* 1. Uploading a banner image with "youtube.channelBanners.insert" method via resumable upload
* 2. Getting user's channel object with "youtube.channels.list" method and "mine" parameter
* 3. Updating channel's banner external URL with "youtube.channels.update" method
*
* #author Ibrahim Ulukaya
*/
/**
* Library Requirements
*
* 1. Install composer (https://getcomposer.org)
* 2. On the command line, change to this directory (api-samples/php)
* 3. Require the google/apiclient library
* $ composer require google/apiclient:~2.0
*/
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
}
require_once __DIR__ . '/vendor/autoload.php';
session_start();
//session_destroy();
/*
* You can acquire an OAuth 2.0 client ID and client secret from the
* {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
* For more information about using OAuth 2.0 to access Google APIs, please see:
* <https://developers.google.com/youtube/v3/guides/authentication>
* Please ensure that you have enabled the YouTube Data API for your project.
*/
$OAUTH2_CLIENT_ID = 'OUR_CLIENT_ID';
$OAUTH2_CLIENT_SECRET = 'OUR_CLIENT_SECRET';
$client = new Google_Client();
$client->setClientId($OAUTH2_CLIENT_ID);
$client->setClientSecret($OAUTH2_CLIENT_SECRET);
$client->setScopes('https://www.googleapis.com/auth/youtube');
$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
FILTER_SANITIZE_URL);
$client->setRedirectUri($redirect);
// Define an object that will be used to make all API requests.
$youtube = new Google_Service_YouTube($client);
// Check if an auth token exists for the required scopes
$tokenSessionKey = 'token-' . $client->prepareScopes();
if (isset($_GET['code'])) {
if (strval($_SESSION['state']) !== strval($_GET['state'])) {
die('The session state did not match.');
}
$client->authenticate($_GET['code']);
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
header('Location: ' . $redirect);
}
if (isset($_SESSION[$tokenSessionKey])) {
$client->setAccessToken($_SESSION[$tokenSessionKey]);
}
// Check to ensure that the access token was successfully acquired.
if ($client->getAccessToken()) {
$htmlBody = '';
try{
// REPLACE with the path to your file that you want to upload for thumbnail
$imagePath = "2560x1440-pixels-image.jpg";
$imageSize = get_headers($imagePath, 1);
// Specify the size of each chunk of data, in bytes. Set a higher value for
// reliable connection as fewer chunks lead to faster uploads. Set a lower
// value for better recovery on less reliable connections.
$chunkSizeBytes = 1 * 1024 * 1024;
// Setting the defer flag to true tells the client to return a request which can be called
// with ->execute(); instead of making the API call immediately.
$client->setDefer(true);
$chan = new Google_Service_YouTube_ChannelBannerResource();
// Create a request for the API's channelBanners.insert method to upload the banner.
$insertRequest = $youtube->channelBanners->insert($chan);
// Create a MediaFileUpload object for resumable uploads.
$media = new Google_Http_MediaFileUpload(
$client,
$insertRequest,
'image/jpeg',
null,
true,
$chunkSizeBytes
);
//$media->setFileSize(filesize($imagePath));
$media->setFileSize($imageSize["Content-Length"]);
// Read the media file and upload it chunk by chunk.
$status = false;
$handle = fopen($imagePath, "rb");
while (!$status && !feof($handle)) {
$chunk = fread($handle, $chunkSizeBytes);
$status = $media->nextChunk($chunk);
}
fclose($handle);
// If you want to make other calls after the file upload, set setDefer back to false
$client->setDefer(false);
$thumbnailUrl = $status['url'];
// Call the API's channels.list method with mine parameter to fetch authorized user's channel.
$listResponse = $youtube->channels->listChannels('brandingSettings', array(
'mine' => 'true',
));
/*echo '<pre>';
print_r($listResponse);
echo '</pre>';*/
$responseChannel = $listResponse[0];
$responseChannel['brandingSettings']['image']['bannerExternalUrl']=$thumbnailUrl;
// Call the API's channels.update method to update branding settings of the channel.
$updateResponse = $youtube->channels->update('brandingSettings', $responseChannel);
$bannerMobileUrl = $updateResponse["brandingSettings"]["image"]["bannerMobileImageUrl"];
$htmlBody .= "<h3>Thumbnail Uploaded</h3><ul>";
$htmlBody .= sprintf('<li>%s</li>',
$thumbnailUrl);
$htmlBody .= sprintf('<img src="%s">', $bannerMobileUrl);
$htmlBody .= '</ul>';
} catch (Google_Service_Exception $e) {
$htmlBody .= sprintf('<p>A service error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
} catch (Google_Exception $e) {
$htmlBody .= sprintf('<p>An client error occurred: <code>%s</code></p>',
htmlspecialchars($e->getMessage()));
}
$_SESSION[$tokenSessionKey] = $client->getAccessToken();
} elseif ($OAUTH2_CLIENT_ID == 'OUR_CLIENT_ID') {
$htmlBody = <<<END
<h3>Client Credentials Required</h3>
<p>
You need to set <code>\$OAUTH2_CLIENT_ID</code> and
<code>\$OAUTH2_CLIENT_ID</code> before proceeding.
<p>
END;
} else {
// If the user hasn't authorized the app, initiate the OAuth flow
$state = mt_rand();
$client->setState($state);
$_SESSION['state'] = $state;
$authUrl = $client->createAuthUrl();
$htmlBody = <<<END
<h3>Authorization Required</h3>
<p>You need to authorize access before proceeding.<p>
END;
}
?>
<!doctype html>
<html>
<head>
<title>Banner Uploaded and Set</title>
</head>
<body>
<?=$htmlBody?>
</body>
</html>
Any suggestions?

twitter application login always asks for permission

I'm using the artdarek package to implement the login process in my web application.
I get a weird behavior by using the twitter login buton action; The application always asks for permission, although the user have accepted it already. Does twitter applications asks for the permission every time we want to login using twitter?
I want to mention that I activated the read,write permission in the settings of my twitter apps.
The action of the twitter login is:
public function loginWithTwitter() {
// get data from input
$token = Input::get( 'oauth_token' );
$verify = Input::get( 'oauth_verifier' );
// get twitter service
$tw = OAuth::consumer( 'Twitter' );
// check if code is valid
// if code is provided get user data and sign in
if ( !empty( $token ) && !empty( $verify ) ) {
// This was a callback request from twitter, get the token
$token = $tw->requestAccessToken( $token, $verify );
// Send a request with it
$result = json_decode( $tw->request( 'account/verify_credentials.json' ), true );
// return $result['source'];
// $message = 'Your unique Twitter user id is: ' . $result['id'] . ' and your name is ' . $result['name'];
//echo $message. "<br/>";
//Var_dump
//display whole array().
dd($result);
// var_dump($result);
return Redirect::route('login');
}
}
// if not ask for permission first
else {
// get request token
$reqToken = $tw->requestRequestToken();
// get Authorization Uri sending the request token
$url = $tw->getAuthorizationUri(array('oauth_token' => $reqToken->getRequestToken()));
// return to twitter login url
return Redirect::to( (string)$url );
}
}
Is there any way to check wether the application was already enabled in twitter so that user will not pass by the permission window every time he login using twitter?

How to get a refresh_token with an auto-approved response?

I have the following code:
if (isset($_REQUEST['logout']))
{
unset($_SESSION['upload_token ']);
}
if (isset($_GET['code']))
{
$client->authenticate($_GET['code']);
$_SESSION['upload_token'] = $client->getAccessToken();
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
}
if (isset($_SESSION['upload_token']) && $_SESSION['upload_token'])
{
$client->setAccessToken($_SESSION['upload_token']);
if ($client->isAccessTokenExpired())
{
echo "The access token is expired.<br>"; // Debug
$client->refreshToken(json_decode($_SESSION['upload_token']));
unset($_SESSION['upload_token']);
}
}
else
{
$authUrl = $client->createAuthUrl();
}
and am receiving the following error:
Uncaught exception 'Google_Auth_Exception' with message 'The OAuth 2.0 access token has expired, and a refresh token is not available. Refresh tokens are not returned for responses that were auto-approved.'
I am assuming I am getting this error because the response was auto-approved.
What should be changed?
UPDATE: I've tried adding this to my code:
$client->setAccessType("online");
$client->setApprovalPrompt("auto");
Based on this question. I still am receiving the same error of missing refresh token.
UPDATE: After kroikie's update, my code looks like the following:
$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->setRedirectUri($redirect_uri);
$client->addScope("https://www.googleapis.com/auth/drive");
$client->setAccessType("offline");
$client->setApprovalPrompt("auto");
$client->setApplicationName("Appraisal App");
$service = new Google_Service_Drive($client);
if (isset($_REQUEST['logout']))
{
unset($_SESSION['upload_token ']);
}
if (isset($_GET['code']))
{
$resp = $client->authenticate($_GET['code']);
$_SESSION['upload_token'] = $client->getAccessToken();
$array = get_object_vars(json_decode($resp));
// store and use $refreshToken to get new access tokens
$refreshToken = $array['refreshToken'];
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
}
if (isset($_SESSION['upload_token']) && $_SESSION['upload_token'])
{
$client->setAccessToken($_SESSION['upload_token']);
if ($client->isAccessTokenExpired())
{
echo "The access token is expired. Let Raph know that you saw this.<br>";
$client->refreshToken($refreshToken);
unset($_SESSION['upload_token']);
}
}
else
{
$authUrl = $client->createAuthUrl();
}
Unfortunately, I still receive the same fatal error when the refresh token is needed.
When the access type is offline, an access token and a refresh token are returned when the user first grants data access. The access token can be used to access the user's data, and the refresh token is stored and used to get a new access token when the initial access token has expired.
So try using offline access type
$client->setAccessType('offline');
and use the refresh token to refresh the client's access token
// $refreshToken is retrieved from the response of the
// user's initial granting access
$client->refreshToken($refreshToken)
UPDATE:
To get the refresh token use something like:
if (isset($_GET['code'])) {
$resp = $client->authenticate($_GET['code']);
$_SESSION['token'] = $client->getAccessToken();
$array = get_object_vars(json_decode($resp));
// store and use $refreshToken to get new access tokens
$refreshToken = $array['refreshToken'];
}
Assuming you want to use the offline access type, you have two choices: either you force the approval prompt (so you never get an auto-approved response):
$client->setAccessType("offline");
$client->setApprovalPrompt("force");
Or you ignore the refresh token and simply get a new auto-approved authorization when your current token is expired. I never tested this but since no user action is required for approval, I assume it works.
You can read more about this here (Change #3: Server-side auto-approval): http://googlecode.blogspot.ca/2011/10/upcoming-changes-to-oauth-20-endpoint.html
Sometimes it's seems that the error is in the code, but in my case was not.
I had the same problem and tried all kind of solution, but the error was in the console.developers.google.com configuration.
I thought was not necessary to confirm the domain in the Credentials configuration.
So when i did it, so the code stopped giving the error.

Verify OAuth Token on Twitter

I'm storing the oauth info from Twitter in a Flash Cookie after the user goes though the oauth process. Twitter says that this token should only expire if Twitter or the user revokes the app's access.
Is there a call I can make to Twitter to verify that my stored token has not been revoked?
All API methods that require authentication will fail if the access token expires. However the specific method to verify who the user is and that the access token is still valid is GET account/verify_credentials
This question may be old, but this one is for the googlers (like myself).
Here is the call to twitter using Hammock:
RestClient rc = new RestClient {Method = WebMethod.Get};
RestRequest rr = new RestRequest();
rr.Path = "https://api.twitter.com/1/account/verify_credentials.json";
rc.Credentials = new OAuthCredentials
{
ConsumerKey = /* put your key here */,
ConsumerSecret = /* put your secret here */,
Token = /* user access token */,
TokenSecret = /* user access secret */,
Type = OAuthType.AccessToken
};
rc.BeginRequest(rr, IsTokenValid);
Here is the response:
public void IsTokenValid(RestRequest request, RestResponse response, object userState)
{
if(response.StatusCode == HttpStatusCode.OK)
{
var user = userState;
Helper.SaveSetting(Constants.TwitterAccess, user);
}
else
{
Dispatcher.BeginInvoke(() => MessageBox.Show("This application is no longer authenticated "))
}
}
I always borrow solutions from SO, this is my first attempt at giving back, albeit quite late to the question.
When debugging manually:
curl \
--insecure https://api.twitter.com/1/account/verify_credentials.json?oauth_access_token=YOUR_TOKEN
I am using TwitterOAuth API and here is the code based on the accepted answer.
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $twitter_oauth_token, $twitter_oauth_secret);
$content = $connection->get("account/verify_credentials");
if($connection->getLastHttpCode() == 200):
// Connection works fine.
else:
// Not working
endif;

Resources