400 error code when using Google oAuth2 server-side authentication - php

In my PHP-based application, I've been using the Google oAuth 2 server-side flow for several years, and it has always worked flawlessly, until recently. I've been reading on any possible breaking API changes, but can't find any. Most questions having similar issues are several years old, so I'm asking a new question. It is particularly strange that this stopped working without any change on my end.
Below details are from my dev environment, but I'm getting similar results on production. This is the URL I use for getting the permission (not sure what the correct terminology is):
https://accounts.google.com/o/oauth2/auth?
scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&state=%2Fprofile
&redirect_uri=http%3A%2F%2Fwww.jungledragon.org%2Fapps%2Fjd4%2Fsignin%2Fgoogle%2Fcallback
&response_type=code
&client_id=652476484487.apps.googleusercontent.com
&approval_prompt=auto
This seems to work correctly. If not given already, the user indeed sees the Google screen to grant access. If the user then approves proceeds, they are redirected back to my application given the callback URL.
With permission given, the next goal is to get some user data. For this, the following code is used:
// get values from the callback URL
parse_str($_SERVER['QUERY_STRING'],$_GET);
$code = $_GET['code'];
$error = $_GET['error'];
$state = $_GET['state'];
// an error reason is returned, something went wrong
if ($error_reason) { return false; }
// our app is recognized, get access token by doing a post to the Google oAuth service
$url = 'https://accounts.google.com//o/oauth2/token';
$data =
"code=" . urlencode($code) .
"&client_id=" . $this->CI->config->item('pd_oauth_google_clientid') .
"&client_secret=" . $this->CI->config->item('pd_oauth_google_clientsecret') .
"&redirect_uri=" . urlencode($this->CI->config->item('pd_oauth_google_callbackurl')) .
"&grant_type=authorization_code";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
// check the result. anything but a 200 return code is an error
$info = curl_getinfo($ch,CURLINFO_HTTP_CODE);
if ($info!=200) { return false; }
As you can see, a CURL POST request is created with several parameters. None of the param values have changed and this has worked for years, yet now stopped working, for unknown reasons.
The particular problem is that the response of the post is the Google Error 404 (Not Found)!! page. This doesn't give me any meaningful info on what could be wrong.
Help is greatly appreciated, as this issue blocks all users on my production site that log in via Google authentication.

https://accounts.google.com//o/oauth2/token
will result in a 404
https://accounts.google.com/o/oauth2/token
will result in
{
"error" : "invalid_request"
}
No idea why your code worked for the last year you have an extra / in there

Related

Problem with Instagram api since July 2022 [duplicate]

I used instagram public api (adding __a=1 to parameters of an url) to get a post detail (caption ,imageUrl, postType, likes, comments , viewsCount). But it seems that Instagram banned that recently and returned a 403. It also asks for login when I try to directly open a post by its usrl.
I tried to use the instagram private api (https://mgp25.github.io/) for getting post details, but after some requests instargam banned that too:
"throttled by instagram because of too many api requests"
Do you have any offer for an alternative?
Actually it is not really banned but now redirects with 302 to auth page. It seems like auth is required when Instagram account and query geoIPs are different. Alternative is to use official API. No scraping can be done, because the profile link now also requires authentication. You can do authenticated scraping but you are limited to 200 queries ( that Instagram sends to get data) per hour.
Instagram blocked all public endpoints with some limitations and hit rate. Now you need to send the user's session to get the response.
Did you notice the same endpoint returning the JSON response when you are logged in on Instagram in the same browser? Yes, that because whenever you are hitting the URL like "https://www.instagram.com/anything/?__a=1", your browser sending the live and valid sessionid to Instagram. Since you are logged in hence Instagram served you well.
Ever you wonder why the same endpoint started to work again after changing the Internet connection from Wifi to Mobile hotspot or try with another internet service provider.
It's because your IP got blocked and no more free hot babes for you until you are logged in.
Below is the PHP code to give a try with sessionid.
<?php
// keyword or user name
$hashtag = $username = "msevylynch";
// $endpoint = "explore/tags/$hashtag"; // hashtag search
$endpoint = $username; // user search
// login in insta account and copy session from browser's cookie tab
$sessionid = '<YOU-SESSION-ID-PICK-FROM-BROWSER-AFTER-LOGIN>';
$ch = curl_init();
https://www.instagram.com/explore/tags/msevylynch/?__a=1
curl_setopt($ch, CURLOPT_URL, "https://www.instagram.com/{$endpoint}/?__a=1");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Cookie: ds_user='.$username.'; igfl='.$username .'; sessionid=' . $sessionid,
'User-Agent: Instagram 7.16.0 Android'
));
$response = curl_exec($ch);
header('Content-Type: application/json');
echo $response;
?>
Still no luck then it means Instagram blocked you or your IP for some time due to
hitting endpoint too early or very fast programmatically
denied the presented challenge
seems it's an automated hit
password is changed
you are logged out
or your internet bill is over due .. ha ha ha
Thank you for the reading this long, much apriceated.
Instagram is getting very strict with __a=1 endpoint. Your best bet in 2021 to get Instagram profile info is to use clean residential proxies
They require residential IPs to access ?__a=1 pages without login. https://webscraping.ai works for it if you use proxy=residential parameter. An example of such a request:
curl "https://api.webscraping.ai/html?api_key=test-api-key&proxy=residential&url=https%3A%2F%2Fwww.instagram.com%2Finstagram%2F%3F__a%3D1"

Connecting to Jenkins Remote API with PHP

In the effort to create a unified CICD process for our applications I am trying to connect to my Jenkins remote access API utilizing this (poorly documented) Jenkins-PHP API which is essentially a wrapper for the cURL functions used for accessing a remote website.
Here is my test connection:
$uname = '';
$pword = '';
$api_token = ''; // not yet used
$jenkins = new \JenkinsKhan\Jenkins("http://$uname:$pword#jenkins.svc.local/jobs");
var_dump($jenkins->isAvailable());
This returns:
bool(false)
The isAvailable() function, part of the Jenkins API class is:
public function isAvailable()
{
$curl = curl_init($this->baseUrl . '/api/json');
curl_setopt($curl, \CURLOPT_RETURNTRANSFER, 1);
curl_exec($curl);
if (curl_errno($curl)) {
return false;
} else {
try {
$this->getQueue();
} catch (RuntimeException $e) {
//en cours de lancement de jenkins, on devrait passer par là
return false;
}
}
return true;
}
EDIT: I added an echo curl_error($curl); to the conditional in the function and it returns:
Could not resolve host %mADA
NOTE: the web server I am running and the Jenkins instance are on the same network and the Jenkins instance is pingable.
I have found some unanswered question on Stack Overflow which are similar, like this one but no others which directly address the problem of connecting to the Jenkins instance.
If I change the URL string (remove the user name, replace the password with the API token, etc.) I get authentication errors at the most and a 403 (access denied) at the very least, so I feel as though I am making some headway but I am lead to believe that no real authentication occurs with the Jenkins instance.
Am I missing something obvious here? How can I make a real connection to the Jenkins remote API?
It turns out there are a couple of problems using the JenkinsKahn API class. I can only blame myself for not seeing that there had been no maintenance on the project in a year, so my current version of Jenkins wouldn't respond properly, but it did give me some hints.
Given the error was:
Could not resolve host
I started looking at the host string I was trying to access and determined that putting the user name and password in the string were making the host un-resolvable (thanks to some questions/interrogation/prodding by a good friend). Using the host string alone resulted in:
access denied (403)
First, this means I was reaching the host, but I was unable to access. Consequently I wrote some pure cURL to deal with the issue of not including the user name and password in the host string but letting cURL do the authentication.
Second, if I appended '/api/json' (according to Jenkin's docs on the subject) to the URL in my web browser I would get back a JSON string. So I made sure to include '/api/json' at the end of the URL for my cURL call.
Here is what I ended up with:
$url = "http://jenkins.svc.local/jobs/api/json";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, "$uname:$pword");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTHBASIC);
$output = curl_exec($ch);
curl_close($ch);
print_r(json_decode($output, true));
This now returns the array of information I was expecting to see and interact with. All that's left to do is use the data as needed and execute commands when required.

Understanding how to publish to a facebook page as a page via a website (app)

I have spent quite some time now trying to establish how, and then the best practise to push some data from my web server to the facebook page created for this purpose.
I have read and understand the process of using access tokens. I have generated an access token for myself, which can be used to post to the page as me ok. I understand this should be used to generate the access token for the page to post as the page which is a ittle more tricky. However, this process involves me logging in and generating an access token which seem inherently bad / inconvenient for an automated process.
For this reason i followed the guides to create an app. I (think I have) linked the app to the page, and thus attempt to push data via the appid and secret from my php code to the page.
When doing this I am presented with this error
{"error":{"message":"(#210) Subject must be a page.","type":"OAuthException","code":210}}
my testing code is this:
$data['picture'] = "http://www.example.com/image.jpg";
$data['link'] = "http://www.example.com/";
$data['message'] = "Your message";
$data['caption'] = "Caption";
$data['description'] = "Description";
$data['access_token'] = $app_token2;
$post_url = 'https://graph.facebook.com/'.$app_id.'/feed';
$url1 = "https://graph.facebook.com/endpoint?key=value&access_token=".$app_id."|". $app_secret ;
echo "<br>$post_url";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $post_url);
//curl_setopt($ch, CURLOPT_URL, $url1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$return = curl_exec($ch);
curl_close($ch);
echo "$return";
I appreciate using the app for server initiated posting using a permanent (ish) secret is the correct way, but I have found very little documentation on how this process is achieved, hence this question.
Your $post_url is pointing to your $app_id variable, the message says it should point to a page, try getting the id of your page from the /me/accounts endpoint of the graph and putting that in there instead. Though I suspect you will need to use a page access_token (also from the /me/accounts endpoint ) to post to your page
Right, I have worked on this for quite some time and found several errors in my code, but have not answered the question fully.
For starters, you do not post to the appid as mentioned above - its just wrong. The code for posting to userid/feed works when using an access token generated from appid + secret using
$url2 = "https://graph.facebook.com/oauth/access_token?client_id=".$app_id."&client_secret=". $app_secret."&grant_type=client_credentials";
this app access token is valid for as long as your app secret is. Also, if I generate a temporary access code for ME via the graph explorer, parse me/accounts manually and use the page token in
$post_url = 'https://graph.facebook.com/'.$page_id.'/feed';
It posts correctlly as the page.
Secondly, all server side call are required to have appsecret_spoof in them which is generated from
$appsecret_proof= hash_hmac('sha256', $app_token2, $app_secret);
now, according to the facebook docs, a http get call to my userid/accounts should yield page access tokens for all pages the user administers (and also presumably the app).
This can also be called directly by using
$url3 = "https://graph.facebook.com/".$page_id."?fields=access_token";
so when a get is made to this address (including app access token & appsecret_spoof) all i get is 'True' ??
Likewise, when the correct call to
$rob1 = "https://graph.facebook.com/".$user_id."/accounts";
I receive an error
{"error":{"message":"(#10) Application does not have permission for this action","type":"OAuthException","code":10}}
OK permission issue then ! Well the documentation says that only manage_pages is required to retrieve the page token from page_id/accounts, so I trawl through lots of pages and find you can do this by calling this url
https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=https://www.facebook.com/connect/login_success.html&response_type=token&scope=read_stream
This throws up via facebook gui an accept / deny page for each scope (i ended up adding manage_pages, publish_stream & read_stream to my app) none of which seem to solve the problem !
Right sorted !! FWIW the code above functions correctly, however the way it is setup on facebook leaves a lot to be desired !!!
I began messing with my app and changed its name, type (was an app linked to the page - now isnt) removed perms and also changed the domain name (removed) and all site url details (also removed). this prompted a different error msg which stated the domains did not match. So, I readded just the app domain & site url, saved and all of a sudden my failed code started working !
Having tidied my code up a little I can now see the page access token just fine as I expected. I just wish the facebook guides would cross reference this setup as it is not at all obvious !!!
my working code ended up as thus ($perm_url is used as one time link to allow perms via gui)
$perm_url = "https://www.facebook.com/dialog/oauth?client_id=".$appid."&redirect_uri=https://www.facebook.com/connect/login_success.html&response_type=token&scope=publish_stream,manage_pages,read_stream,status_update";
echo "<br>Test";
$facebook = new Facebook(array('appId' => $appid , 'secret' => $appsecret ,));
$access_token = $facebook->getAccessToken();
$pageinfo = $facebook->api("/".$page_id."?fields=access_token");
$page_access_token = $pageinfo['access_token'];
echo "<br>Holy Grail = $page_access_token ";

Facebook API: /oauth/access_token not working

I am trying to obtain a user access token from Facebook with the PHP-SDK. The server-side log-in process works great, redirecting to the correct page and providing $code too.
After the redirect (and checking whether $code exists) I then call the following API method to exchange $code for a user token (API parameters are suppressed here):
$fb->api('/oauth/access_token',array(
'client_id' => APP_ID,
'client_secret' => APP_SECRET,
'redirect_uri' => REDIRECT_URI,
'code' => $code
));
$fb_token = $fb->getAccessToken();
echo $fb_token;
Unfortunately, all I get from this script is still the app token. In fact, reducing the script to just the following does not make any difference:
$fb_token_user = $fb->getAccessToken();
echo $fb_token_user;
So I assume it is all about the /oauth/access_token call which for some reason is not working or at least does no action. It does not return any errors either.
I have tried and tested several alternatives, such as the get_file_contents() method suggested in the Facebook tutorial as well as adding additional parameters to the above API call (e.g. type=client_cred and more), but never succeeding.
Does anybody see why the API call is not working? Is it the script or could it be some app setting on Facebook?
Thanks in advance!
Solved! The code in the question is still not working in spite of ever so many threads on this and other communities stating it does (oddly enough it seemed to work for them).
So I figured I had to go back to the file_get_contents() method as explained by Facebook and it turns out this method was previously not working because allow_url_fopen is disabled on my server. Not wanting to undergo the risk of enabling it, I discovered cURL as a work-around.
And here is the working code:
// cURL Load Function
function cURLget ($ch_url) {
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$ch_url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_USERAGENT,$_SERVER['HTTP_USER_AGENT']);
$ch_send = curl_exec($ch);
curl_close($ch);
return $ch_send;
};
// Obtain User Token
$fb_token_get = cURLget("https://graph.facebook.com/oauth/access_token"
. "?client_id=" . APP_ID
. "&client_secret=". APP_SECRET
. "&redirect_uri=" . urlencode(REDIRECT_URI)
. "&code=" . $CODE
);
$fb_token_params = null;
parse_str($fb_token_get,$fb_token_params);
// Print Token Data
echo "Token: " . $fb_token_params['access_token']
. "<br />Expires: " . $fb_token_params['expires'];
Thanks to #FabioAntunes for trying to help me with the original code and to #ShawnECarter for his script for the cURL Load Function.
Stumbled upon this problem today too. Seems my PHP SDK (v.3.2.2) offers a function that solves the problem: setExtendedAccessToken(). (Does pretty much the same thing: Calls graph's "/oauth/access_token" and exchanges the old token against a "long-lived" one).

Posting a like via app on facebook only returns true and does nothing

I was trying to get the feeds of friends' fan pages with a cURL and to post a like via app.
The cURL GET works fine, but when it comes to liking the object (that has for sure likes enabled because it's facebook), all I get is a boolean (and no action).
I had seen on SO that you post a like with
($access_token, "https://graph.facebook.com/$post_id/likes", 'POST')
However, it is not working (it says either that the app has no permissions to do that, or that I need a valid url).
I have tried all possible solutions but nothing seems to work. The profile is mine, the access token too, and I gave publish_stream permissions to my own app.
After having given a try to the SDK PHP Likbrary, I tried a direct cURL post, with the following code:
function likeit($url){
//open connection
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, $url);
curl_exec($ch);
curl_close($ch);
}
The execution i a puzzle. When it does not return an OAuth Exception it returns boolean and stops there (there is no way for me to "like" the post I want to like). The last attempt (but I've tried them all, even the whole url in some tests) is
foreach ($feeds->data as $feed_data)
$message = $feed_data->message;
$title = $feed_data->name;
$link = $feed_data->link;
$id = $feed_data->id;
$myaccesstoken = "longlastingaccesstokenstring";
$post=likeit($myaccesstoken, "https://graph.facebook.com/$post_id/likes", 'POST');
Does anybody have a suggestion on how to do this? It seems trivial and yet there is no way for me to accomplish it. Thank you so much in advance!
I've found a solution, and thus am posting it here for future reference (hoping it is helpful for anybody with the same problem):
the only problem was that after the new permissions with facebook I needed to re-authorize my app.
After that, it is possible to post a like with the SDK facebook library, normally:
$facebook->api("/$id/likes", 'post', array(
'access_token' => $myaccesstoken));
No need to use cURL directly. Hope this helps someone with the same question.

Categories