I was wondering if you could help me out with a bit of code for a cCURL request using PHP, I'm trying to retrieve data from the fpl api that would show my league standings. The url for the league standings api is - https://fantasy.premierleague.com/api/leagues-classic/my_league_id/standings/?page_new_entries=1&page_standings=1 I can see the data via the browser but when I try to retrieve it with a curl request with PHP it comes back with a 403 error with the message "Authentication credentials were not provided". That would mean that I would need login credentials to retrieve it.
After looking into it using dev tools and postman, I now know that I need to get a csrf token by logging in then save the token to use when I make the request for the league standings. I have no idea how to go about this, I kind of do but I would really appreciate if someone could give it a go for me.
What I would need to do is make a POST request to https://users.premierleague.com/accounts/login/ with this form data -
"login" => "my_email",
"password" => "my_password",
"app" => "plfpl-web",
"redirect_uri" => "https://fantasy.premierleague.com/",
After making the request I would need to capture the csrf token cookie, which I believe would be in the hidden input with the name - "csrfmiddlewaretoken" and save it in a variable.
Once getting the token and saving it, I would then make a GET request to https://fantasy.premierleague.com/api/leagues-classic/my_league_id/standings/ with placing the csrf token variable that I saved into the headers and then json decode that data so I'm able to echo out the league details.
I'm pretty sure that's how to do it but I'm not that great at PHP and was wondering if there is any savour out there that could help a brother out. Any help would be much appreciated :)
I've started with the first part, making the initial post request, but have had no luck in returning the token. Here's my code so far -
<?php
$cookie = "cookies.txt";
$url = 'https://users.premierleague.com/accounts/login/';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$response = curl_exec($ch);
curl_close($ch);
// var_dump($response);
$dom = new DOMDocument;
#$dom->loadHTML($response);
$tags = $dom->getElementsByTagName('input');
for($i = 0; $i < $tags->length; $i++) {
$grab = $tags->item($i);
if($grab->getAttribute('name') === 'csrfmiddlewaretoken') {
$token = $grab->getAttribute('value');
}
}
echo $token;
?>
<?php
// id of the league to show
$league_id = "your_league_id";
// set the relative path to your txt file to store the csrf token
$cookie_file = realpath('your_folder_dir_to_the_txt_file/cookie.txt');
// login url
$url = 'https://users.premierleague.com/accounts/login/';
// make a get request to the official fantasy league login page first, before we log in, to grab the csrf token from the hidden input that has the name of csrfmiddlewaretoken
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt ($ch, CURLOPT_COOKIEJAR, $cookie_file);
curl_setopt ($ch, CURLOPT_COOKIEFILE, $cookie_file);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
$dom = new DOMDocument;
#$dom->loadHTML($response);
// set the csrf here
$tags = $dom->getElementsByTagName('input');
for($i = 0; $i < $tags->length; $i++) {
$grab = $tags->item($i);
if($grab->getAttribute('name') === 'csrfmiddlewaretoken') {
$token = $grab->getAttribute('value');
}
}
// now that we have the token, use our login details to make a POST request to log in along with the essential data form header fields
if(!empty($token)) {
$params = array(
"csrfmiddlewaretoken" => $token,
"login" => "your_email_address",
"password" => "your_password",
"app" => "plfpl-web",
"redirect_uri" => "https://fantasy.premierleague.com/",
);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
/**
* using CURLOPT_SSL_VERIFYPEER below is only for testing on a local server, make sure to remove this before uploading to a live server as it can be a security risk.
* If you're having trouble with the code after removing this, look at the link that #Dharman provided in the comment section.
*/
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//***********************************************^
$response = curl_exec($ch);
// set the header field for the token for our final request
$headers = array(
'csrftoken ' . $token,
);
}
// finally, we now have everything we need to make the GET request to retrieve the league standings data. Enjoy :)
$fplUrl = 'https://fantasy.premierleague.com/api/leagues-classic/' . $league_id . '/standings/';
curl_setopt($ch, CURLOPT_URL, $fplUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
if(!empty($token)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$response = curl_exec($ch);
$league_data = json_decode($response, true);
curl_close($ch);
echo '<pre class="card">';
print_r($league_data);
echo '</pre>';
?>
Related
I’m building a login system in php where I need to use credentials from another website, I’m using an API to login to another server and I’m doing it using cURL. The server where the login credentials are stored does create a cookie with a unique tolken after the user has logged in correctly and this cookie is important to view other webpages and interrogate this pages using other APIs.
This is what I’ve done so far and it seems to work fine, in the login controller php file I’ve got this code
$km_username = filter_var($_POST['userName'], FILTER_SANITIZE_STRING);
$km_user_password = $_POST['userPassword'];
$cookieFile = "cookies.txt";
if(!file_exists($cookieFile)) {
$fh = fopen($cookieFile, "w");
fwrite($fh, "");
fclose($fh);
}
$url = 'https://www.apiwebsite.com/api/login.jsp?';
$fields = array(
'userid' => $km_username,
'password' => $km_user_password
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile); // Cookie aware
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile); // Cookie aware
$content = curl_exec($ch);
curl_close($ch);
In the page where I want to interrogate the server to get other datas I’ve got
$dates = array(
'd_inizio' => '01/01/2017',
'd_fine' => '31/12/2017'
);
$url = "https://www.apiwebsite.com/api/ricevute.jsp?";
$cookie = "../../km-controllers/cookies.txt";
$ch = curl_init ($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($dates));
curl_setopt ($ch, CURLOPT_COOKIEFILE, $cookie);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec ($ch);
So basically after user has logged into the website cURL saves a cookie txt file into my server and this allows me to use that file any other time i want to make another call using for example a different api
Now the question is: what happen if I’ve got more than one user logging into the system? Do I need to create x number of cookies according on how many users log into the system? Would it not be simpler to save the cookie into the user’s browser?
Yes, you should use a different file for each client. What you can do is use tempnam() to generate a unique filename for the client, and save this in a session variable, then use it as the cookie jar. The login controller can do this:
session_start();
if (!isset($_SESSION['cookiefile'])) {
$cookiefile = tempnam(".", "cookie");
$_SESSION['cookiefile'] = basename($cookiefile);
}
And then the later page can use
$cookie = "../../km-controllers/" . $_SESSION['cookiefile'];
When the user logs out, you should delete this file and remove the session variable.
There's nothing that will automatically pass the cookies through from the curl session to the client browser or vice versa. If you don't want to save the cookies in a file, you can use curl_getinfo($ch, CURLINFO_COOKIELIST) to get the cookies, but you'll then have to parse the info yourself, and later use CURLOPT_COOKIE to set each cookie when making future calls. The cookie file automates all this.
Full code for login controller.
session_start(); // This needs to be at the very beginning of your script, before anything that produces output
//...
$km_username = filter_var($_POST['userName'], FILTER_SANITIZE_STRING);
$km_user_password = $_POST['userPassword'];
if (!isset($_SESSION['cookiefile'])) {
$cookieFile = tempnam(".", "cookie");
$_SESSION['cookiefile'] = basename($cookiefile);
file_put_contents($cookieFile, "");
}
$cookieFile = $_SESSION['cookiefile'];
$url = 'https://www.apiwebsite.com/api/login.jsp?';
$fields = array(
'userid' => $km_username,
'password' => $km_user_password
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile); // Cookie aware
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile); // Cookie aware
$content = curl_exec($ch);
curl_close($ch);
And the later interrogator:
session_start(); // at very beginning
// ...
$dates = array(
'd_inizio' => '01/01/2017',
'd_fine' => '31/12/2017'
);
$url = "https://www.apiwebsite.com/api/ricevute.jsp?";
if (!isset($_SESSION['cookiefile'])) {
die("no cookie file");
}
$cookie = "../../km-controllers/" . $_SESSION['cookiefile'];
$ch = curl_init ($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($dates));
curl_setopt ($ch, CURLOPT_COOKIEFILE, $cookie);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec ($ch);
Context: I have a WordPress plugin that allows users to authenticate with Bitly so that they can use link shortening features if they desire to do so.
Bitly requires one callback URL to be stored in the app settings, so I created a standalone script on my server that processes the authentication process. The overall handshake actually looks something like this:
The user clicks a link taking them to the Bitly authorization page for my app.
If they agree, they are forwarded to my script with a code.
My script exchanges that code to Bitly for another code.
Once the codes are all acquired, it reaches out to the user's domain to store the codes and to retreive the URL of the options page on that user's URL so that we can redirect the user back home.
We then redirect the user back to the options page that they had just clicked away from.
Problem: However, a very small handful of users are getting the following error just prior to the authentication process being complete:
Warning: Header may not contain more than a single header, new line
detected in /home/warfarep/public_html/bitly_oauth.php on line 72.
Sample Code:
function sw_file_get_contents_curl($url){
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
curl_setopt($ch, CURLOPT_FAILONERROR, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
$cont = #curl_exec($ch);
$curl_errno = curl_errno($ch);
curl_close($ch);
if ($curl_errno > 0) {
return 0;
}
return $cont;
}
// Check if this is the first pass and we have the generic code
if(isset($_GET['code'])):
// Retreive the information
$code = $_GET['code'];
$client_ID = 'blahblahblah';
$client_secret = 'blahblahblah';
$redirect_url = 'blahblahblah';
$state = $_GET['state'];
$url = 'https://api-ssl.bitly.com/oauth/access_token';
$fields = array(
'code' => urlencode($code),
'client_id' => urlencode($client_ID),
'client_secret' => urlencode($client_secret),
'redirect_uri' => urlencode($redirect_url),
'state' => urlencode($state)
);
//url-ify the data for the POST
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string, '&');
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_HTTPHEADER, array('Accept: application/json'));
//execute post
$response = curl_exec($ch);
//close connection
curl_close($ch);
$response = json_decode($response , true);
$ajax_url = $state .= '?action=sw_bitly_oauth&access_token='.$response['access_token'].'&login='.$response['login'];
$wp_response = sw_file_get_contents_curl($ajax_url);
$wp_response = rtrim($wp_response , '0');
header('Location: '.$wp_response);
^^^^^^ This is line 72 from the error message
endif;
Question: Is there anything that you can see that would prevent headers from already being sent prior to the redirect on line 72? How do I fix this Bitly oauth "single header" error? Thanks!
I have tried all several methods and approaches to this problem and I'm stumped. I'm trying to log into www.senderscore.org with php. The site's log in is a post form to their index page. I need to do this because I need to lookup several IPs and log the information on a regular basis. I have tried posting with curl but I have had no luck. Every attempt just returns the page as if I did not attempt to log in. If anyone could help out with a code snippet I'd appreciate it very much.
edit: The latest attempt's block of code. this is the code inside a class function.
$username= $this->username;
$password= $this->password;
$url = 'www.senderscore.org/index.php';
$fields = array(
'email'=>$username,
'password'=>$password,
'action'=>"localLogin",
'Submit'=>"Sign in",
'remember'=>'1'
);
$postvars='';
$sep='';
foreach($fields as $key=>$value)
{
$postvars.= $sep.urlencode($key).'='.urlencode($value);
$sep='&';
}
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL,$url);
curl_setopt($curl,CURLOPT_POST,true);
curl_setopt($curl,CURLOPT_POSTFIELDS,$postvars);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
$data = curl_exec($curl);
if ($data === false) {
$data = curl_error($curl);
}
curl_close($curl);
return $data;
Try to look at this script, it should work with post; i haven't tested it:
$username = 'your_username';
$password = 'your_password';
$loginUrl = 'http://www.path-to-login.com/login/';
//init curl
$ch = curl_init();
//Set the URL to work with
curl_setopt($ch, CURLOPT_URL, $loginUrl);
// ENABLE HTTP POST - this is important in your case
curl_setopt($ch, CURLOPT_POST, 1);
//Set the post parameters - make sure to match username and password
curl_setopt($ch, CURLOPT_POSTFIELDS, 'user='.$username.'&pass='.$password);
//Handle cookies for the login
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
//Setting CURLOPT_RETURNTRANSFER variable to 1 will force cURL
//not to print out the results of its query.
//Instead, it will return the results as a string return value
//from curl_exec() instead of the usual true/false.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//execute the request (the login)
$store = curl_exec($ch);
//the login is now done and you can continue to get the
//protected content.
//set the URL to the protected file
curl_setopt($ch, CURLOPT_URL, 'http://www.site-logging-into.com/protected/file.zip');
//execute the request
$content = curl_exec($ch);
//save the data to disk
file_put_contents('~/file.zip', $content);
Hello stackoverflow members.
I'm not a person who likes to ask for a help but in this case it's IMO the only way to solve my problem. Google didn't help me much.
So. My problem:
I want to get some data using Twitch API. Sounds easy? I wish it was. Below I'm posting my actual code (it's small but it was modified various of times and now it look like...):
$user = json_decode(file_get_contents('https://api.twitch.tv/kraken/oauth2/authorize?response_type=code&client_id=MY_CORRECT_CLIENT_ID&redirect_uri=http://localhost/php/twitch.php&scope=user_read'), true);
print_r($user); // returns nothing
$token = $user['access_token'];
print_r($token); // same as above
$ch = curl_init();
// some stupid curls
curl_setopt($ch, CURLOPT_URL, 'https://api.twitch.tv/kraken/streams/followed');
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, 'Authorization: OAuth '.$token );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$retval = curl_exec($ch);
curl_close($ch);
$result = json_decode($retval, true);
It returns... Nothing. So I used ready solution from discussions.twitch. (I wish I could write the name of the author of this code but I'm too tired to search it again. Either way thanks!):
$ch = curl_init("https://api.twitch.tv/kraken/oauth2/token");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
$fields = array(
'client_id' => 'blablabla_correct',
'client_secret' => 'blablabla_also_correct',
'grant_type' => 'authorization_code',
'redirect_uri' => 'http://localhost/php/twitch.php',
'code' => $_GET['code']
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
$data = curl_exec($ch);
$response = json_decode($data, true);
//var_dump($response);
$access_token = $response["access_token"];
echo $access_token;
function get_data($url) {
$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$returnobj = curl_exec($ch);
curl_close($ch);
return $returnobj;
}
$testobj = json_decode(get_data("https://api.twitch.tv/kraken/user?oauth_token=".$access_token."&client_id=".$fields['client_id']));
echo "<br>Data: ";
print_r($testobj);
This code above is a bit better. Only a bit. It returns Error 401. Why? Because it can't get auth token. Well, it's something but not what I wanted to get. What should I do now? Maybe it's fault of localhost address?
FAQ(?):
Yes, I'm using correct data from my Twitch application settings page.
Yes, I'm confused
You're making two calls to the Twitch API, and you need to debug them independently.
For now, just skip the second call. Focus on the one where you grab your access token.
Try this:
// to start, just use the code you've already got:
$ch = curl_init("https://api.twitch.tv/kraken/oauth2/token");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
$fields = array(
'client_id' => 'blablabla_correct',
'client_secret' => 'blablabla_also_correct',
'grant_type' => 'authorization_code',
'redirect_uri' => 'http://localhost/php/twitch.php',
'code' => $_GET['code']
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
$data = curl_exec($ch);
// Now, here we believe the first error comes into play, so let's check it out
print_r($data); // confirm that this is not what we want
$info = curl_getinfo($ch); // let's get some details about that last request
// print it out and see what we get
echo '<pre>';
print_r($info);
echo '</pre>';
... that should give you a starting point to figure out what's going on. If you see an auth token, then you're not accessing it in the right way. If you don't, the info will give you some information about why.
I don't know what redirect_uri is (can you link to docs that explain it?) so I can't know if the localhost reference is a problem there.
I am trying to login Joomla 1.6/3.0 by curl in PHP but not success.
I had try method from joomla 1.5
$uname = "id";
$upswd = "pswd";
$url = "http://www.somewebpage.com";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url );
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE );
curl_setopt($ch, CURLOPT_COOKIEJAR, './cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, './cookie.txt');
curl_setopt($ch, CURLOPT_HEADER, FALSE );
$ret = curl_exec($ch);
if (!preg_match('/name="([a-zA-z0-9]{32})"/', $ret, $spoof)) {
preg_match("/name='([a-zA-z0-9]{32})'/", $ret, $spoof);
}
// POST fields
$postfields = array();
$postfields['username'] = urlencode($uname);
$postfields['passwd'] = urlencode($upswd);
$postfields['lang'] = '';
$postfields['option'] = 'com_login';
$postfields['task'] = 'login';
$postfields[$spoof[1]] = '1';
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
$ret = curl_exec($ch);
But it 's show forbidden
Joomla! normally from the web browser will send a token, to make sure the form was posted from a browser (and not from somewhere outside, like you are trying to do).
If it's not posted from a browser, an error like 'The most recent request was denied because it contained an invalid security token. Please refresh the page and try again.'
You may want to look for an autentication plugin that supports what you are trying to do. For example the Autologin plugin.