2

I am building an application that is built upon an API that requires Basic Authentication. I have made many calls and wrapped up the CURL requests inside a class that I've made,

I'm using a cookie jar that I use like this:

curl_setopt($curl_handle, CURLOPT_COOKIEJAR, "cookie.txt");
curl_setopt($curl_handle, CURLOPT_COOKIEFILE, "cookie.txt");

I am trying to keep sessions by using cookie.txt to store the cookies and its been working great. However, today I came across an alarming discovery. When someone else (on a different computer) goes to my app, they can see my session information (probably because it's using the same file as reference for the session). I have thought that perhaps I could generate a new "cookie jar" for each visitor, but this will probably not work when it goes to production. The quantity of users is going to be in the thousands at least, so I think this means that I would need a cookie file for each visit right?

This doesn't seem practical and not to mention that I would have to create the cookie file programmatically. Has anybody else come across this issue before? Any suggestions would be a real help.

Perhaps there's a CURL setopt solution that would uniquely distribute the cookies amongst visits?

Thanks!

Doug Molineux
  • 12,283
  • 25
  • 92
  • 144
  • 1
    Since you're talking about cookies I don't think you're using "Basic Authentication" which looks like `http://user:password@website.com` - I think your problem outlines why normally APIs don't require you to send cookies. Are you certain this is the only way? – Halcyon Aug 08 '11 at 23:12
  • Hi Frits, well I'm open to suggestions but I wanted to build the app on top of AJAX calls, and as I understand it, it's impossible to authenticate with AJAX over an HTTPS connection, since JSONP strips the headers. CURL allows me to set the username and password using CURLOPT_USERPWD. – Doug Molineux Aug 08 '11 at 23:17
  • Not if you're using Basic Authentication. It works fine over https, like: `https://user:password@secure.website.com` - if you want to use AJAX then why are you using cookies? I'm confused now. – Halcyon Aug 08 '11 at 23:22
  • Sorry I can see why this is confusing, there's Session management related functionality in the API in that they use a salesforce "access token" that should be set in the current users session. from what I read the username:password in the url isn't supported in all browsers: http://support.microsoft.com/kb/834489 – Doug Molineux Aug 08 '11 at 23:35
  • I have tried to do the username and password in the url like you are suggesting and didn't have any luck with it: http://stackoverflow.com/questions/3780702/jsonp-to-acquire-json-from-https-protocol-with-jquery – Doug Molineux Aug 08 '11 at 23:40
  • Another question related to the username:password in the URL: http://stackoverflow.com/questions/5679416/possible-to-send-basic-auth-in-link-in-java – Doug Molineux Aug 08 '11 at 23:43
  • I'm assuming your server is doing the actual API calls. In that case there is no browser involved and Basic Authentication would work for you as expected. – Halcyon Aug 08 '11 at 23:51
  • We are talking about doing Basic Auth through AJAX, so the request would be made from the browser. AJAX + Basic Auth + SSL is unreliable. – Doug Molineux Aug 09 '11 at 00:55

1 Answers1

1

If you can expose the cookie to the user if you turn on curl_setopt($curl_handle, CURLOPT_HEADER,1) the headers returned by the curl exec will be present a the top of the content, you could match these out of the top of the content and pass them to the clients browser for retention, then pass any user cookies back through the curl process for the next request.

something crude I made a while ago:

  if(is_array($_COOKIE))
  {
    foreach($_COOKIE as $cookiename => $cookievalue)
    {
      if($cookievalue)
      {
        if(get_magic_quotes_gpc())
        {
          $cookievalue = stripslashes($cookievalue);
        }
        $cookies[] = $cookiename .'='. urlencode($cookievalue);
      }
    }
    if(is_array($cookies))
    {
      curl_setopt($curl_handle, CURLOPT_COOKIE,implode('; ',$cookies));
    }
  }

after the curl exec

  preg_match_all('%HTTP/\\d\\.\\d.*?(\\r\\n|\\n){2,}%si', $curl_result, $header_matches);
  $headers = split("\r\n", str_replace("\r\n\r\n",'',array_pop($header_matches[0])));
  if(is_array($headers))
  {
    foreach ($headers as $header)
    {
      preg_match('#(.*?)\:\s(.*)#', $header, $header_matches);
      if(isset($header_matches[1]))
      {
        $headers[$header_matches[1]] = $header_matches[2];
      }
      // SET THE COOKIE
      if($header_matches[1] == 'Set-Cookie')
      {
        header('Set-Cookie: ' . $header_matches[2],false);
      }
    }
  }
  # Remove the headers from the response body
  $curl_result = preg_replace('%HTTP/\\d\\.\\d.*?(\\r\\n|\\n){2,}%si','',$curl_result);
Scuzzy
  • 12,186
  • 1
  • 46
  • 46
  • Just did a search to see what else was there and thought this was interesting http://svetlozar.net/page/free-code.html – Scuzzy Aug 08 '11 at 23:17
  • 1
    So basically you're using the client as a bin to store the cookies? Clever but kind of nasty too :P – Halcyon Aug 08 '11 at 23:23
  • Well if you took just the concept of using CURLOPT_HEADER, you could extract and DB the cookies yourself without having to resort to writing the cookies to the jar file, gladly my situation isn't mission critical and it's only for a vehicle inventory listings. Otherwise you'd pretty much have to resort to setting different CURLOPT_COOKIEJAR files for each unique user. :) – Scuzzy Aug 08 '11 at 23:29