Viewed   120 times

I'm trying to connect to an API, authenticate a user and then view the user details. This is accomplished by first accessing the login endpoint at

http://api.example.com/login/<username>/<password>

to log in and then the following to view user details:

http://api.example.com/user/

This all works in a web browser. However, once I try to use Curl, the login works fine, but when attempting to view user details, I get back a 401, unauthorized error. I believe this is because Curl isn't saving the session cookies properly? Can someone point out why it isn't working and how to fix it? I've tried searching stack exchange, however, none of the solutions I've tried have worked for my situation. The code I'm using to curl the endpoints is shown below. Thanks!

define("COOKIE_FILE", "cookie.txt");

// Login the user
$ch = curl_init('http://api.example.com/login/joe/smith');
curl_setopt ($ch, CURLOPT_COOKIEJAR, COOKIE_FILE); 
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
echo curl_exec ($ch);

// Read the session saved in the cookie file
echo "<br/><br/>";
$file = fopen("cookie.txt", 'r');
echo fread($file, 100000000);   
echo "<br/><br/>";

// Get the users details
$ch = curl_init('http://api.example.com/user');
curl_setopt ($ch, CURLOPT_COOKIEJAR, COOKIE_FILE); 
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
echo curl_exec ($ch);

This code will output:

HTTP/1.1 200 OK Date: Mon, 22 Oct 2012 21:23:57 GMT Server: LiteSpeed Connection: close X-Powered-By: PHP/5.3.14 Set-Cookie: cfapi=f481129c9616b8f69cc36afe16466545; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Content-Type: application/json X-Powered-By: CFWAPI 0.1a Content-Length: 46 {"status":200,"msg":"Successfully Logged In."}

# Netscape HTTP Cookie File # http://curl.haxx.se/rfc/cookie_spec.html # This file was generated by libcurl! Edit at your own risk. api.example.com FALSE   /   FALSE   0   cfapi 94f63b07ccf7e34358c1c922341c020f 

HTTP/1.1 401 Unauthorized Date: Mon, 22 Oct 2012 21:23:57 GMT Server: LiteSpeed Connection: close X-Powered-By: PHP/5.3.14 Set-Cookie: cfapi=a8eb015a7c423dde95aa01579c4729a4; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 Pragma: no-cache Content-Type: application/json X-Powered-By: CFWAPI 0.1a Content-Length: 49 {"status":401, "msg":"You need to login first!"}

 Answers

2

You also need to set the option CURLOPT_COOKIEFILE.

The manual describes this as

The name of the file containing the cookie data. The cookie file can be in Netscape format, or just plain HTTP-style headers dumped into a file. If the name is an empty string, no cookies are loaded, but cookie handling is still enabled.

Since you are using the cookie jar you end up saving the cookies when the requests finish, but since the CURLOPT_COOKIEFILE is not given, cURL isn't sending any of the saved cookies on subsequent requests.

Saturday, September 17, 2022
2

The problem is that the client is not remembering/transmitting the PHP session id.

When an HTTP client makes a request to a php script (via an HTTP server), it must include the session id in the request if it wishes to continue a previously started session. This can be done either in the HTTP headers as a cookie or as a URL parameter (named PHPSESSID by default). If you do not want to use PHP's default session variable name, or if you want to use a POST variable instead of a URL parameter, then you can use any request variable or URL parameter you wish (whether it be GET, POST, or COOKIE), but then you will need to manually interpret this variable on the server-side.

Here are three solutions, in order of most recommended to least recommended.

  1. Turn on cookie support in cUrl or
  2. Pass the session id as a URL parameter or
  3. Pass the session id as a request variable (post/cookie) or a URL parameter that does not use the name expected by PHP, and then manually start the session on the server-side using that session id.

Solution #1: Turn on cookie support in cUrl

PHP uses the session id in the cookie to reload your session data each time you make a request from that client.

In this case, the client is cUrl. You need to setup your cUrl request to allow/use cookies. This is done by setting the CURLOPT_COOKIEJAR and CURLOPT_COOKIEFILE options.

session_start();
$_POST["username"]= "user";
$_POST["password"]= "password";

$ch = curl_init();

$url = 'signin.php';

//Name of a file to store cookie data in.
//If the file does not exist, it will be created.  
//cUrl (or your web server) needs to have write permissions to the folder.
$cookieFile = "/some/writable/folder/filename";


curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($_POST));
curl_setopt($ch,CURLOPT_POSTFIELDS, $_POST);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);

//Tell cUrl about the cookie file
curl_setopt($ch,CURLOPT_COOKIEJAR, $cookieFile);  //tell cUrl where to write cookie data
curl_setopt($ch,CURLOPT_COOKIEFILE, $cookieFile); //tell cUrl where to read cookie data from

$result = json_decode(curl_exec($ch),true);
curl_close($ch);

Any subsequent cUrl calls that use $cookieFile for CURLOPT_COOKIEJAR and CURLOPT_COOKIEFILE will have the same session data as prior calls.

Solution #2: Pass the session id in the URL query string using the expected parameter name (PHPSESSID by default, but this can be changed)

You can append the session id to all urls like this: somepage.php?PHPSESSID=sessionidgoeshere

"PHPSESSID" is the variable name that is used by default in PHP. If the server is setup to use a non-default name, then you would need to use that variable name instead.

With solution #2, you will still need to store the session id on the client-side somehow.

Solution #3: Pass the session id as a request variable or a URL parameter and then manually start the session on the server-side using that session id.

This solution is not recommended for normal situations. Unlike the previous solutions, this one requires changes to the server-side script as well as the client-side (cUrl). This solution is only useful if you specifically want to send the session id as something other than a URL parameter or cookie, or if you want to use a variable name other than the name that the server is expecting. Place the following code in your server-side PHP that is handling the request, prior to starting the session: session_id($_POST[<param_name>]); or session_id($_GET[<param_name>]); or session_id($_COOKIE[<param_name>]);


I suggest using Solution #1 unless you have a compelling reason not to.


Also, PHP doesn't care whether the request is a GET or a POST or any other HTTP request method. Regardless of the HTTP request method, if the session id is passed as a URL parameter or in a cookie, then the related session will persist on the server-side.

Monday, September 12, 2022
2

Works fine for me. Here are few things to think about:

  • Are you sure $GET['appID'] is set? Perhaps the script is being run via a POST?
  • Comment out ini_set('display_errors', false); and see if any notices/warnings/errors appear.
  • Is the script running on the same box as the curl command line?
Monday, December 5, 2022
 
1

With the CURLOPT_REFERRER option, which you had already made use of.

curl_setopt($ch, CURLOPT_REFERER, "your referer website");

[EDIT] I don't think that website can find referer of your localhost website.

Try this on Google Chrome Browser

In the Developer Tools, go to the Network view (if it wasn't open when you loaded the page, you'll need to reload to get it populated). Click on the main page request -- it should be at the top of the list. When you click, the right pane will probably show the HTML for it. Click on the "Headers" tab on the right side. The Referer is shown in the list of Request Headers.

Wednesday, October 12, 2022
 
4

As mentioned here, you might want to try to do the cURL request without having the session open, e.g. by doing session_write_close() before sending the request and session_start() after you've handled it.

Tuesday, December 27, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :