I am developing gadget with tech requirements: "no Cookie, no Session".
I have the following code:
<?php
class LinkedIn
{
private $options;
private $consumer;
private $client;
private $token;
public function __construct($params)
{
// set Zend_Oauth_Consumer options
$this->options = array(
'version' => '1.0',
'localUrl' => $params['localUrl'],
'callbackUrl' => $params['callbackUrl'],
'requestTokenUrl' => 'https://api.linkedin.com/uas/oauth/requestToken',
'userAuthorizationUrl' => 'https://api.linkedin.com/uas/oauth/authorize',
'accessTokenUrl' => 'https://api.linkedin.com/uas/oauth/accessToken',
'consumerKey' => $params['apiKey'],
'consumerSecret' => $params['secretKey']
);
// instanciate Zend_Oauth_Consumer class
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Oauth_Consumer');
$this->consumer = new Zend_Oauth_Consumer($this->options);
}
public function connect()
{
// Start Session to be able to store Request Token & Access Token
session_start ();
if (!isset ($_SESSION ['ACCESS_TOKEN'])) {
// We do not have any Access token Yet
if (! empty ($_GET)) {
// SECTION_IF
// But We have some parameters passed throw the URL
// Get the LinkedIn Access Token
$this->token = $this->consumer->getAccessToken ($_GET, unserialize($_SESSION ['REQUEST_TOKEN']));
// Store the LinkedIn Access Token
$_SESSION ['ACCESS_TOKEN'] = serialize ($this->token);
} else {
// SECTION_ELSE
// We have Nothing
// Start Requesting a LinkedIn Request Token
$this->token = $this->consumer->getRequestToken ();
// Store the LinkedIn Request Token
$_SESSION ['REQUEST_TOKEN'] = serialize ($this->token);
// Redirect the Web User to LinkedIn Authentication Page
$this->consumer->redirect ();
}
} else {
// We've already Got a LinkedIn Access Token
// Restore The LinkedIn Access Token
$this->token = unserialize ($_SESSION ['ACCESS_TOKEN']);
}
// Use HTTP Client with built-in OAuth request handling
$this->client = $this->token->getHttpClient($this->options);
}
}
It's working perfect. But REQUEST_TOKEN stored in SESSION. How can I put it to query string in SECTION_ELSE, and get it back in SECTION_IF? Thanks for all the advice.
The key point is that your system needs to:
1. persist the OAuth tokens between user requests to your server, and
2. tie them to a specific user.
Using a session, whose id comes from either a cookie or from the querystring, is one way to do that.
But if sessions are off the table, then you need some other way to identify the current user and store his OAuth tokens.
If you are truly working in a no-session environment, then how do you even know who the user is? Basic Auth? In the absence of user authentication on your side, I don't see how you'll be able associate OAuth tokens to specific users.
Related
I have a Magento 2.3 store that I'm trying to sync some data to Quickbooks Online.
I've created a QBO App but this is my first time using oauth and I'm a bit confused on how to store and use the access / refresh tokens.
According to Quickbooks doc I need to store the latest refresh token:
Each access token can only be valid for an hour after its creation. If you try to make an API call after an hour with the same access token, the request will be blocked by QBO. That is what refresh token used for. It is used to request a new access token after access token expired, so you can still access to the QBO company after an hour. Just remember, whenever you make a refreshToken API call, always STORE THE LATEST REFRESH TOKEN value in your session or database. In QuickBooks Online OAuth 2 protocol, it is not the access token you should store, it is the refresh token you need to store.
So my question is, how do I properly store and call upon my refresh token to generate a new access token each time my API makes a call to sync data.
Currently, I'm directly using my OAuth tokens by hard coding them into my helper file:
<?php
namespace Company\Module\Helper;
use QuickBooksOnline\API\DataService\DataService;
class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
public function getConfigurationSetting()
{
$dataService = DataService::Configure(array(
'auth_mode' => 'oauth2',
'ClientID' => '<<my ClientID',
'ClientSecret' => '<<my ClientSecret>>',
'accessTokenKey' => 'xxxxxx',
'refreshTokenKey' => 'xxxxxx',
'QBORealmID' => "123xxxxxxx",
'baseUrl' => 'Development'
));
$OAuth2LoginHelper = $dataService->getOAuth2LoginHelper();
$refreshedAccessTokenObj = $OAuth2LoginHelper->refreshToken();
$error = $OAuth2LoginHelper->getLastError();
if ($error){
$dataService->throwExceptionOnError(true);
} else {
$dataService->updateOAuth2Token($refreshedAccessTokenObj);
}
return $dataService;
}
}
And then I'm calling that from my controller:
<?php
namespace Company\Module\Observer;
use Magento\Framework\Event\ObserverInterface;
use QuickBooksOnline\API\DataService\DataService;
class CreateQbInvoice implements ObserverInterface
{
protected $helperData;
public function __construct(
\Company\Module\Helper\Data $helperData
){
$this->helperData = $helperData;
}
public function execute()
{
// Prep Data Services
$dataService = $this->helperData->getConfigurationSetting();
...
Now this works until my access token expires and I need to generate a new one, I'm just not sure how to update my access token and store the new refresh token properly to keep access to my app always refreshed.
once you get access token. use that to get token and refresh token.
you will get token, refresh token, expiry for token, expiry for refresh token
save all data in database with current time.
for QuickBook token will expire after few hours but refresh token will not expire up to 1 year.
so for every request you will first check if token expire get new token with refresh token. refresh token will return token and new refresh token replace that will previous one
because you don't have and mechanism to refresh the token . i guess you need a permanent access token.
https://www.oauth.com/oauth2-servers/access-tokens/access-token-lifetime/
use QuickBooksOnline\API\DataService\DataService;
$dataService = DataService::Configure(array(
'auth_mode' => 'oauth2',
'ClientID' => 'your client id',
'ClientSecret' => 'your client secret',
'RedirectURI' =>'redirect url',
'scope' => "com.intuit.quickbooks.accounting openid profile",
'baseUrl' => 'development or production'
));
$OAuth2LoginHelper = $dataService->getOAuth2LoginHelper();
$authorizationCodeUrl = $OAuth2LoginHelper->getAuthorizationCodeURL();
if( isset($_GET['code']) ) {
$accessTokenObj = $OAuth2LoginHelper->exchangeAuthorizationCodeForToken( $_GET['code'], 'your company id') );
// save these for later use
$refreshTokenValue = $accessTokenObj->getRefreshToken();
// Expires every 12 hours.
$refreshTokenExpiry = $accessTokenObj->getRefreshTokenExpiresAt();
// The access token and access token expiration.
$accessTokenValue = $accessTokenObj->getAccessToken();
$accessTokenExpiry = $accessTokenObj->getAccessTokenExpiresAt();
}
I am using Cosenary Instagram-PHP-API (https://github.com/cosenary/Instagram-PHP-API) and have been able to successfully retrieve user media from user accounts. However, when I redirect clients to another php page (e.g. 'action.php'), I loose all the authentication and get the '400' error message saying that: The access_token provided is invalid.' I have tried passing authCode and access_token to the second page and used them for authentication but still couldn't retrieve data. How should I store and pass authentication to the second page? I am trying to delete comments and unfollow people on the second pages.
Here is the code I am using (from examples folder):
$instagram = new Instagram(array(
'apiKey' => '####',
'apiSecret' => '#####',
'apiCallback' => '...../success.php'
));
// receive OAuth code parameter
$code = $_GET['code'];
// check whether the user has granted access
if (isset($code)) {
// receive OAuth token object
$data = $instagram->getOAuthToken($code);
$username = $data->user->username;
// store user access token
$instagram->setAccessToken($data);
// now you have access to all authenticated user methods
$result = $instagram->getUserMedia();
} else {
// check whether an error occurred
if (isset($_GET['error'])) {
echo 'An error occurred: ' . $_GET['error_description'];
}
}
I've written a twitter api application using the following tutorial:
http://www.youtube.com/watch?v=GQaPt-gQVRI
How can I modify the script to generate a timeline stream that is specific to a user so that the application when run will show user's timeline stream and not mine (since i wrote the app and therefore it has my twitter credentials)
Thanks
the php application validates my twitter credentials using the following:
<?php
require 'tmhOAuth.php'; // Get it from: https://github.com/themattharris/tmhOAuth
// Use the data from http://dev.twitter.com/apps to fill out this info
// notice the slight name difference in the last two items)
$connection = new tmhOAuth(array(
'consumer_key' => 'my key',
'consumer_secret' => 'my secret',
'user_token' => 'my token', //access token
'user_secret' => 'my user secret' //access token secret
));
// set up parameters to pass
$parameters = array();
if ($_GET['count']) {
$parameters['count'] = strip_tags($_GET['count']);
}
if ($_GET['screen_name']) {
$parameters['screen_name'] = strip_tags($_GET['screen_name']);
}
if ($_GET['twitter_path']) { $twitter_path = $_GET['twitter_path']; } else {
$twitter_path = '1.1/statuses/user_timeline.json';
}
$http_code = $connection->request('GET', $connection->url($twitter_path), $parameters );
if ($http_code === 200) { // if everything's good
$response = strip_tags($connection->response['response']);
if ($_GET['callback']) { // if we ask for a jsonp callback function
echo $_GET['callback'],'(', $response,');';
} else {
echo $response;
}
} else {
echo "Error ID: ",$http_code, "<br>\n";
echo "Error: ",$connection->response['error'], "<br>\n";
So without having to pass a new username in the api call, how can i add a snippet to require the user to log in? and if i add that snippet for the user to log in, will the api automatically populate the authentication strings with the user's?
You can send a get request to the following url to get a users timeline.
https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=twitterapi&count=2
You can replace the parameters screen_name with the username you want to access, and you can replace count with the number of tweets you would like to get, count is optional and doesn't have to be included.
You can read more about statuses/user_timeline on the office twitter API site: https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline
If you wish to get a user to sign in then your best bet would be to use the twitteroauth library by abraham
Download and include in your project, then include the library and start a session.
require("twitteroauth/twitteroauth.php");
session_start();
Then create a new instance and authenticate with your app details. You can set a url to redirect to when the user authenticates. You also need to cache your tokens.
$twitteroauth = new TwitterOAuth('YOUR_CONSUMER_KEY', 'YOUR_CONSUMER_SECRET');
$request_token = $twitteroauth->getRequestToken('http://example.com/loggedin.php');
$_SESSION['oauth_token'] = $request_token['oauth_token'];
$_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret'];
Redirect the user to twitter to authenticate
header('Location: '.$twitteroauth->getAuthorizeURL($request_token['oauth_token']));
In the file that you set twitter to redirect to you need to re-authenticate using the tokens created. Twitter will also add a parameter to your url which you use to create a access token for that user. Now when you send GET requests to twitter, it does it on behalf of the user logged in.
require("twitteroauth/twitteroauth.php");
session_start();
$twitteroauth = new TwitterOAuth('YOUR_CONSUMER_KEY', 'YOUR_CONSUMER_SECRET', $_SESSION['oauth_token'], $_SESSION['oauth_token_secret']);
$user_info = $twitteroauth->get('account/verify_credentials');
print_r($user_info);
You can get additional details from $user_info which you can cache or store in a database, which will allow you to remember users that have already authenticated. You will need to use oauth_token and oauth_secret, something like this.
$twitteroauth = new TwitterOAuth('YOUR_CONSUMER_KEY', 'YOUR_CONSUMER_SECRET', 'OAUTH_TOKEN', 'OAUTH_SECRET');
I have twitter username and password. What I want is, when a client adds any new article from the admin side I want its url be auto twit. I dont want to bother client to login to twitter each time he adds an article. Is there any way to auto login using Abraham twitteroauth library. Thankyou
Twitter requires first to Authorize a client app, then you'll able to auto-tweet on certain occasions (i.e. publishing new article). For a detailed depiction you may take a look at this Twitter module for Chyrp that I've created. It uses the Abraham's Twitter oAuth library. There's also a clear example inside the abraham's library archive that may clear this up a bit.
On the other hand, the CMS/Blog you're using for your client's site, should provide hooks (callbacks) in order to know when a post is being created, in order to call the Tweet method accordingly.
Example from the linked Twitter module for Chyrp:
1) Authorize with Twitter:
static function admin_chweet_auth($admin) {
if (!Visitor::current()->group->can("change_settings"))
show_403(__("Access Denied"), __("You do not have sufficient privileges to change settings."));
# If the oauth_token is old redirect
if (isset($_REQUEST['oauth_token']) && $_SESSION['oauth_token'] !== $_REQUEST['oauth_token'])
Flash::warning(__("Old token. Please refresh the page and try again."), "/admin/?action=chweet_settings");
# New TwitteroAuth object with app key/secret and token key/secret from SESSION
$tOAuth = new TwitterOAuth(C_KEY, C_SECRET, $_SESSION['oauth_token'], $_SESSION['oauth_token_secret']);
$access_token = $tOAuth->getAccessToken($_REQUEST['oauth_verifier']);
# Save access tokens locally for future tweeting.
$config = Config::current();
$config->set("chweet_oauth_token", $access_token["oauth_token"]);
$config->set("chweet_oauth_secret", $access_token["oauth_token_secret"]);
$config->set("chweet_user_id", $access_token["user_id"]);
$config->set("chweet_username", $access_token["screen_name"]);
unset($_SESSION['oauth_token']);
unset($_SESSION['oauth_token_secret']);
if (200 == $tOAuth->http_code)
Flash::notice(__("Chweet was successfully Authorized to Twitter."), "/admin/?action=chweet_settings");
else
Flash::warning(__("Chweet couldn't be authorized."), "/admin/?action=chweet_settings");
}
2) add_post (trigger)
public function add_post($post) {
fallback($chweet, (int) !empty($_POST['chweet']));
SQL::current()->insert("post_attributes",
array("name" => "tweeted",
"value" => $chweet,
"post_id" => $post->id));
if ($chweet and $post->status == "public")
$this->tweet_post($post);
}
3) Tweet-it method (truncated).
public function tweet_post($post) {
$tOAuth = new TwitterOAuth(C_KEY, C_SECRET, $config->chweet_oauth_token, $config->chweet_oauth_secret);
$user = $tOAuth->get("account/verify_credentials");
$response = $tOAuth->post("statuses/update", array("status" => $status));
return $response;
}
Im using the following code to read to consumer_key and consumer_secret from config.php, pass it to twitter and retrieve some bits of information back from them.
What the script below attempts to do is 'cache' the request_token and request_secret. So in theory I should be able to reuse those details (all 4 of them to automatically tweet when required).
<?php
require_once('twitteroauth/twitteroauth.php');
require_once('config.php');
$consumer_key = CONSUMER_KEY;
$consumer_secret = CONSUMER_SECRET;
if (isset($_GET["register"]))
{
// If the "register" parameter is set we create a new TwitterOAuth object
// and request a token
/* Build TwitterOAuth object with client credentials. */
$oauth = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
$request = $oauth->getRequestToken();
$request_token = $request["oauth_token"];
$request_token_secret = $request["oauth_token_secret"];
// At this I store the two request tokens somewhere.
file_put_contents("request_token", $request_token);
file_put_contents("request_token_secret", $request_token_secret);
// Generate a request link and output it
$request_link = $oauth->getAuthorizeURL($request);
echo "Request here: " . $request_link . "";
die();
}
elseif (isset($_GET["validate"]))
{
// This is the validation part. I read the stored request
// tokens.
$request_token = file_get_contents("request_token");
$request_token_secret = file_get_contents("request_token_secret");
// Initiate a new TwitterOAuth object. This time we provide them with more details:
// The request token and the request token secret
$oauth = new TwitterOAuth($consumer_key, $consumer_secret,
$request_token, $request_token_secret);
// Ask Twitter for an access token (and an access token secret)
$request = $oauth->getAccessToken();
// There we go
$access_token = $request['oauth_token'];
$access_token_secret = $request['oauth_token_secret'];
// Now store the two tokens into another file (or database or whatever):
file_put_contents("access_token", $access_token);
file_put_contents("access_token_secret", $access_token_secret);
// Great! Now we've got the access tokens stored.
// Let's verify credentials and output the username.
// Note that this time we're passing TwitterOAuth the access tokens.
$oauth = new TwitterOAuth($consumer_key, $consumer_secret,
$access_token, $access_token_secret);
// Send an API request to verify credentials
$credentials = $oauth->oAuthRequest('https://twitter.com/account/verify_credentials.xml', 'GET', array());
// Parse the result (assuming you've got simplexml installed)
$credentials = simplexml_load_string($credentials);
var_dump($credentials);
// And finaly output some text
echo "Access token saved! Authorized as #" . $credentials->screen_name;
die();
}
?>
When i run /?verify&oauth_token=0000000000000000 - It works however trying to resuse the generated tokens etc... I get a 401
Here is the last bit of code where I attempt to reuse the details from Twitter combined with my consumer_key and consumer_secret and get the 401:
require_once('twitteroauth/twitteroauth.php');
require_once('config.php');
// Read the access tokens
$access_token = file_get_contents("access_token");
$access_token_secret = file_get_contents("access_token_secret");
// Initiate a TwitterOAuth using those access tokens
$oauth = new TwitterOAuth($consumer_key, $consumer_key_secret,
$access_token, $access_token_secret);
// Post an update to Twitter via your application:
$oauth->OAuthRequest('https://twitter.com/statuses/update.xml',
array('status' => "Hey! I'm posting via #OAuth!"), 'POST');
Not sure whats going wrong, are you able to cache the details or do i need to try something else?
You can't store the OAuth tokens in cache and to more than 1 request with it, as OAuth is there to help make the system secure, your "oauth_token" will contain some unique data, this token will only be able to make one call back to twitter, as soon as the call was made, that "oauth_token" is no longer valid, and the OAuth class should request a new "oauth_token", thus making sure that every call that was made is secure.
That is why you are getting an "401 unauthorized" error on the second time as the token is no longer valid.
twitter is still using OAuth v1 (v2 is still in the draft process even though facebook and google already implemented it in some parts)
The image below describes the flow of the OAuth authentication.
Hope it helps.
A while ago I used this to connect to twitter and send tweets, just note that it did make use of some Zend classes as the project was running on a zend server.
require_once 'Zend/Service/Twitter.php';
class Twitter {
protected $_username = '<your_twitter_username>';
protected $_token = '<your_twitter_access_token>';
protected $_secret = '<your_twitter_access_token_secret>';
protected $_twitter = NULL;
//class constructor
public function __construct() {
$this->getTwitter();
}
//singleton twitter object
protected function getTwitter() {
if (null === $this->_twitter) {
$accessToken = new Zend_Oauth_Token_Access;
$accessToken->setToken($this->_token)
->setTokenSecret($this->_secret);
$this->_twitter = new Zend_Service_Twitter(array(
'username' => $this->_username,
'accessToken' => $accessToken,
));
$response = $this->_twitter->account->verifyCredentials();
if ($response->isError()) {
throw new Zend_Exception('Provided credentials for Twitter log writer are wrong');
}
}
return $this->_twitter;
}
//send a status message to twitter
public function update( $tweet ) {
$this->getTwitter()->status->update($tweet);
}
}
In your second script, it looks like you aren't setting the Consumer Key and Consumer Secret when you create your TwitterOAuth instance.
// Initiate a TwitterOAuth using those access tokens
$oauth = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $access_token, $access_token_secret);