I travel a lot and I had a cool idea of making a site, whereiskavi.com, to just show the city I'm in at the time. Simple, I use latitude! Or so I thought.
My research has presented me with a challenge. oauth needs to be prompted from the browser, and obviously I can't authorize every hit. Now I've used apps that don't constantly re-prompt me for authorization, but so far the only way I've been able to do this is to acquire an oauth json string and paste it in, then wait for it to expire. This code below works, but only till an expiration date.
My question - how do I permanently authorize my app to see my account always?
Here's my successful code, so far:
<?php
require_once '../../src/Google_Client.php';
require_once '../../src/contrib/Google_LatitudeService.php';
require_once 'gogeocode-0.2/src/GoogleGeocode.php';
$client = new Google_Client();
$client->setClientId('0000000000000.apps.googleusercontent.com');
$client->setClientSecret('abcdefghijklmnopqrstuvwxyz');
$client->setApplicationName("whereiskavi.com");
$mapsApiKey = 'mApSApIKEy';
$access_token = '{"access_token":"CENSORSHIP_YEAH","token_type":"Bearer","expires_in":3600,"refresh_token":"THIS_MIGHT_BE_SENSITIVE DATA","created":1351291247}';
$client->setAccessToken($access_token);
$service = new Google_LatitudeService($client);
$location = $service->currentLocation->get();
$geo = new GoogleGeocode($mapsApiKey);
$result = $geo->geocode( $location['latitude'].', '.$location['longitude']);
$result = $result['Placemarks'][0];
echo '<h1>'.strtoupper($result['Locality'].', '.$result['AdministrativeArea']).'</h1>';
?>
I really just need to figure out how to have perpetual oauth sessions or something!
My understanding is that the token will live as long as you want it to (Ie. until you revoke it).
I've tried your code above, but am getting the following error:
Fatal error: Uncaught exception 'Google_AuthException' with message 'Error refreshing the OAuth2 token, message: '{ "error" : "invalid_grant" }'
Even tho I have set my clientID/secret etc as configured with Google.
Well, folks, it seems that the API was slightly misleading for me. I've had the same access token in this for almost a month and it seems to keep renewing its self. I'll leave this question open in case anyone has more info - we'll see if it lasts 2 months!
Related
Update: This does actually refresh Oauth2 tokens. I had an error in my code that was causing it to fail. In the hopes that this helps someone else I have decided to not delete it
I'm running into problems with regenerating oauth2tokens using a refresh token in the AdWords API (v201702). Using the code sample found here, I'm able to authenticate users after they grant access but I can't figure out how to generate a new oauth2token using the refresh token once the original token has expired. The only way I can make requests to the API is with constant reauthentication. This is the code I have right now:
$oauth2Token = (new OAuth2TokenBuilder())
->withClientId($clientId)
->withClientSecret($clientSecret)
->withRefreshToken($refreshToken)
->build();
$adWordsSession = (new AdWordsSessionBuilder())
->withOAuth2Credential($oauth2Token)
->withDeveloperToken($developerToken)
->build();
When I try to use that adWordsSession to make API calls, I get a bad request. The $oauth2Token doesn't contain an accessToken so I'm assuming it's not properly generating. Can anyone help?
I am building a restful API (PHP) to serve iOS and Android applications and I would like to implement facebook login on both apps.
The flaw is like the following :
Clients ( ios or Android ) login with facebook and send an access_token to the restful api
verify if the access_token is authorized to use the application
If token is valid, get user data from graph.
Merge accounts and generate token for different queries.
For security purpose to avoid getting random tokens thatthey don't belong to my APP, I would like to make a test call to check if a token is authorized and valid or not ?
I know many similar questions might be already answered but none of them really give me the right answer and I don't really have experience with facebook graph.
I found this solution :
https://graph.facebook.com/oauth/access_token?client_id=APP_ID&client_secret=SECRET_APP_ID&grant_type=fb_exchange_token&fb_exchange_token=ACCESS_TOKEN
This works somehow .. it whether give me an error, or an access token (string format not JSON) and I am not sure if this is the best way to test or not.
Note: I am still in early stage of development, if you have any suggestion on my flow please let me know, I might be doing things the wrong way ?
What works for my application (code with explanation below)...
$fb = new Facebook\Facebook([
'app_id' => 'XXXXXXX',
'app_secret' => 'XXXXXXX',
'default_graph_version' => 'v2.5',
]);
// My app pulls users' access tokens & page ID from a database here and stores in $fb_access_token & $fb_page_id variables
$fb_access_token = 'YOU OR YOUR USERS ACCESS TOKEN GOES HERE';
$fb_page_id = 'ID OF FACEBOOK PAGE OR USER';
$fb->setDefaultAccessToken($fb_access_token);
// CHECK IF ACCESS TOKEN SITLL WORKS
try{
$page = $fb->get('/'.$fb_page_id.'?fields=id', $fb_access_token);
} catch(Facebook\Exceptions\FacebookResponseException $e) {
echo 'Graph returned an error: ' . $e->getMessage();
$graphError = 'Yes';
} catch(Facebook\Exceptions\FacebookSDKException $e) {
echo 'Facebook SDK returned an error: ' . $e->getMessage();
$sdkError = 'Yes';
}
// IF ACCESS TOKEN STILL WORKS...CONTINUE WITH SCRIPT. THIS PREVENTS ACCESS TOKEN FAILURE FROM BREAKING SCRIPT.
if(!isset($graphError) && !isset($sdkError)){
// CONTINUE WITH SCRIPT
}
Explanation: you are taking the access token in question, and attempting to make a GET Request to the Facebook API. Only continue with the rest of your script IF there are NO ERRORS.
You could also add an ELSE statement at the end to maybe redirect the user to a page where they can re-authenticate their account/access token, depending on what your app is doing.
My app uses a couple of WHILE Loops to go through my database of users, and depending on certain column/cell values, it POSTS to their Facebook page for them...
Before this solution...when the Loop came across an invalid Access Token, it "broke" and did not execute the script for the rows following the "unauthenticated user" because it was making a failed request.
Hope this helps someone!
“Random” tokens would not work anyway. (Tokens issued by Facebook are encrypted, so the API can tell whether a token is genuine, or just "random". At most you'd need to worry about what a user possible could using a token for a different app, or one they themselves granted more permissions than you asked them for.)
Just request the user details using the access token you got - if it is not valid because someone tried to “fake” it, then the API response will tell you so.
The docs have a chapter about securing API requests, go check that out as well: https://developers.facebook.com/docs/graph-api/securing-requests
this is literally giving me nightmares! I'm working with Google API for the first time. I want to allow a website to add a calendar event to my calendar, without authentication.
From reading a LOT of tutorials, I've gathered that I need to access as a 'Service User'. I've put together some code based on online examples, but it just isn't working, and I'm not getting any useful errors as to why! It's not that I can't add to the calendar - I can't even get THAT far, it just seems to error as soon as the script calls the first Google API class.
<?php
ini_set('include_path', '/home/sites/mysite.co.uk/public_html/testsite');
include "/google/src/Google/Client.php";
include "/google/src/Google/Service/Calendar.php";
echo "includes OK";
// Service Account info
//$calName = '#####group.calendar.google.com';
$client_id = '####';
$service_account_name = 'account-1####.iam.gserviceaccount.com';
$key_file_location = '/google/####.json';
if (!strlen($service_account_name) || !strlen($key_file_location))
echo missingServiceAccountDetailsWarning();
echo "ok so far";
$client = new Google_Client();
echo "ok call to Google";
$client->setApplicationName("MyApp");
As you can see I've added some basic debugging to try to work out where the problem is. So when I run the file, it gets as far as 'ok so far' and ever seems to get to 'ok call to Google'. Sooo, I'm assuming it's something to do with my credentials?
1 - Do I need to update Client.php in the google api files?
2 - I am not 100% sure which credentials go where. I've created an API key and a service account in Google Developers Console, but I am confused. I've also given full access in the calendar sharing to the service account email address.
Any help would be really appreciated.
Nicky
I've got a strange problem that I've tried to solve but I've tried a whole day and it just doesn't work, so I hope maybe someone else can help me with this.
I've build a CMS and after you login you see the dashboard.
On this dashboard you can click on a button to connect your account with Google - because I want my customers to be able to connect their Google Analytics account.
Everything works fine, I've got tokens and the refresh token and everything seems to work. Even when I request my user profile data I get it printed on my screen as an array. But when I try to get the accounts that are available to view for the connected user i get this error:
Uncaught exception 'Google_Service_Exception' with message 'Error calling GET
https://www.googleapis.com/analytics/v3/management/accounts/~all/webproperties
key=xxxxxxxxxxxxxxxxxxxxxxxxxx: (401) Login Required'
I just don't understand why I get the message 'Login required'.
Below you can see my script.
require_once('/Google/Client.php');
require_once('/Google/Service/Analytics.php');
// call object
$client = new Google_Client();
$client->setApplicationName("Google Analytics - CMS title");
$client->setClientId('xxxxxxxxxxxxxxxxx');
$client->setClientSecret('xxxxxxxxxxxxxxxx');
$client->setRedirectUri('xxxxxxxxxxxxxxxxxxx');
$client->setDeveloperKey('xxxxxxxxxxxxxxxxxxx');
$client->setApprovalPrompt('auto');
$client->setAccessType('offline');
$client->setScopes(array(
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/analytics'
));
// decode
$token = $token; // this comes from my database and it's json encoded
// connect
$client->setAccessToken($token);
// call service
$service = new Google_Service_Analytics($client);
// get accounts from analytics
$accounts = $service->management_accounts->listManagementAccounts();
When I try to var_dump $accounts I don't see anything because the error already occurred (Login required)
I think you are going to ask me now if my token is correct but it is because I tested it with other api calls.. it's just not working for this specific analytics request.
I hope someone can help me with this.
Thanks,
Pim vd Molen
UPDATE:
Something really strange just happened. I don't know how this is possible but the error just changed into another error:
Uncaught exception 'Google_Service_Exception' with message 'Error calling GET
https://www.googleapis.com/analytics/v3/management
/accounts?key=xxxxxxxxxxxxxxxxxx: (403) Access Not Configured.
Please use Google Developers Console to activate the API for your project.
I've enabled the Google Analytics service ofcourse, but don't know which one i also need to enable.
The 401 error clearly states that the credentials are wrong. The Token might be valid for retrieving Data, but for retrieving user management information, you need a particular grant when asking for that token, please look here in the table you see the additional value for the scope parameter to set in your OAuth request.
not sure if you have solved this yet, but I've documented the process, with photos here:
https://circlical.squarespace.com/blog/2014/7/18/getting-zend-framework-2-and-googles-api-to-play-nice
I've successfully made my way through the LinkedIn OAuth process (using the REST API - OAuth 1.0a). However I'm having trouble with my first API call after the callback. I set the UserToken, UserTokenSecret and UserVerfier in the library I am writing, and this call this function to get my profile information:
public function getUserProfile()
{
$consumer = new OAuthConsumer($this->consumer_key, $this->consumer_secret, NULL);
$auth_token = new OAuthConsumer($this->getUserToken(), $this->getUserTokenSecret());
$access_token_req = new OAuthRequest("GET", $this->access_token_endpoint);
$params['oauth_verifier'] = $this->getUserVerifier();
$access_token_req = $access_token_req->from_consumer_and_token($this->consumer,
$auth_token, "GET", $this->access_token_endpoint, $params);
$access_token_req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer,
$auth_token);
$after_access_request = $this->doHttpRequest($access_token_req->to_url());
$access_tokens = array();
parse_str($after_access_request,$access_tokens);
# line 234 below
$access_token = new OAuthConsumer($access_tokens['oauth_token'], $access_tokens['oauth_token_secret']);
// prepare for get profile call
$profile_req = $access_token_req->from_consumer_and_token($consumer,
$access_token, "GET", $this->api_url.'/v1/people/~');
$profile_req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer,$access_token);
$after_request = $this->doHttpRequest($profile_req->to_url());
var_dump($after_request);
}
The function var_dumps a string, which is the basic synopsis of my profile:
string(402) " User Name etc. etc. http://www.linkedin.com/profile?viewProfile=&key=28141694&authToken=HWBC&authType=name&trk=api*a137731*s146100* "
That's good. However, the minute I refresh the page, the same function call fails with:
Undefined index: oauth_token, line number: 234
(this line marked with comment in above code block).
Then, of course, the var_dump reports this error from LinkedIn:
string(290) " 401 1310652477038 R8MHA2787T 0 [unauthorized]. The token used in the OAuth request is not valid. "
something to note:
the user token, secret, and verifier are persisted during the initial authorization callback (right before this function is called). So, they are the same during the first call (when it works, right after coming back from linkedin) and during a page reload (when it fails on line 234).
Also, I must admit I'm not 100% sure I understand everything that's going on in this function. I actually took examples from this tutorial (about a different service, not linkedin) http://apiwiki.justin.tv/mediawiki/index.php/OAuth_PHP_Tutorial and combined it with the information I gathered from the LinkedIn API documentation, spread throughout their developer site. Most notable was the addition of the 'verifier' which the tutorial did not use.
Any insight into this problem would be greatly appreciated. Thanks in advance.
-Nick
UPDATE
The only way I've been able to get this going is to do a new OAuth handshake every single time. Is this the way it's supposed to happen? I was under the impression that once I got my user token/secret and verifier, that I could then use these for continuous API calls until the token expired or was revoked.
As it is now, every time the page reloads I'm requesting a new user token, secret and verifier, then immediately calling to get the user profile (which succeeds). Next reload, I get a whole new key/secret and verifier. Seems like quite a lot of work for each call, and as I understood it, you should be able to perform offline operations with this method - and if I need new authorization each time, then I guess I can't do that?
Well. I've finally figured out what was going on so thought I'd post the answer here, just in case someone else runs into this.
The example that I was using as a guide was flawed. After the access token is retrieved, you should then create a new OAuthRequest object, instead of using the existing $access_token_req instance.
So this:
// prepare for get profile call
$profile_req = $access_token_req->from_consumer_and_token($consumer,
$access_token, "GET", $this->api_url.'/v1/people/~');
$profile_req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer,$access_token);
$after_request = $this->doHttpRequest($profile_req->to_url());
Should be changed to this:
$api_req = new OAuthRequest("GET", $this->api_url.$api_call);
// prepare for get profile call
$api_req = $api_req->from_consumer_and_token($consumer,
$access_token, "GET", $this->api_url.'/v1/people/~');
$api_req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer,$access_token);
$after_request = $this->doHttpRequest($api_req->to_url());