3

I am trying to build a PHP Based REST API, but I am stuck with this issue. I have got session_start() in PHP code and a simple Sign In, Sign Out script, which accepts the same username and password to be authenticated:

<?php
  session_start();
  header("Access-Control-Allow-Origin: *");
  header("Content-type: application/json");
  $message = array();
  if ($_GET["action"] == "signin") {
    if (count($_POST) && isset($_POST["username"]) && isset($_POST["password"]) && $_POST["username"] == $_POST["password"]) {
      $message["user"] = $_POST["username"];
      $message["success"] = true;
      $_SESSION["user"] = $message["user"];
    } else {
      unset($message["user"]);
      $message["success"] = false;
      unset($_SESSION["user"]);
    }
  } elseif ($_GET["action"] == "signout") {
    session_destroy();
    $message["success"] = true;
  } elseif ($_GET["action"] == "whoami") {
    $message["success"] = true;
    $message["user"] = isset($_SESSION["user"]) ? $_SESSION["user"] : "Guest";
  }
  die(json_encode($message));
?>

And I am using POSTMan (Chrome Extension) to login and check and everything works fine. But when I use my jQuery's $.getJSON() and $.post() methods, when I try action=whoami, I am just getting Guest. My jQuery code:

$.getJSON("http://localhost/api.php?action=whoami");
// Gives Guest. Okay! :)
$.post("http://localhost/api.php?action=signin", {
  username: "admin", password: "admin"
});
// Gives me success with the user logged in.
$.getJSON("http://localhost/api.php?action=whoami");
// Gives Guest Again! :O

I have already tried the same thing using POSTMan and it worked charm. But using jQuery this didn't work. So, I tried using:

$.ajaxSetup({
  cache: false
});

Nevertheless, I also tried appending a random string like this, but same response:

Not this as well. Can someone please help me proceed? This is a show stopper for me.

$.getJSON("http://localhost/api.php?action=whoami");
// Gives Guest. Okay! :)
$.post("http://localhost/api.php?action=signin", {
  username: "admin", password: "admin"
});
// Gives me success with the user logged in.
$.getJSON("http://localhost/api.php?action=whoami&kill=cache");
// Gives Guest Again! :O
  • Are you running the app (javascript) from the same port as the API? – Alon Eitan May 08 '16 at 16:19
  • Yes, both are on port 80 but different domains – Anjali Madas May 08 '16 at 16:21
  • Are you making cross domain requests ? – 11thdimension May 08 '16 at 16:23
  • Oh, there's your problem (Read [this](http://stackoverflow.com/questions/14611545/preserving-session-variables-across-different-domains) and [this](http://stackoverflow.com/questions/13806701/secure-and-flexible-cross-domain-sessions)). I've implemented [Authorization with JWT](http://www.sitepoint.com/php-authorization-jwt-json-web-tokens/) and it's working great for cross-domain requests – Alon Eitan May 08 '16 at 16:23
  • @11thdimension The OP uses `header("Access-Control-Allow-Origin: *");` right? – Praveen Kumar Purushothaman May 08 '16 at 16:25
  • 1
    @PraveenKumar Yes, and one of the suggestions was to set a session cookie for the domain. Have I missed anything? Please correct me because AFAIK it has something to do with the session cookie and the different domains – Alon Eitan May 08 '16 at 16:31
  • @AlonEitan Even I had the same problem, but instead, I used to host it in my own local PHP file, but how is it working with POSTMan? I didn't take an effort to try to check what's the problem. – Praveen Kumar Purushothaman May 08 '16 at 16:33
  • @PraveenKumar request is made to `localhost`. However if it's a cross domain request cookies won't be sent by the browser due the CORS policy. To avoid it server should set `Access-Control-Allow-Credentials: true` and client should use `withCredentials:true` in the `XHR` headers. – 11thdimension May 08 '16 at 16:34
  • @11thdimension Got a simple solution of using `named sessions` and that worked fine in my http://localhost/ and posted it as an answer. Yours seems to be nice too. Lemme have a look on it. So that I can change my old applications. – Praveen Kumar Purushothaman May 08 '16 at 16:40
  • @PraveenKumar I'm not completely sure why it's working with Postman. That's also why I wrote it as a comment and not as answer - My suggestion was based on a similar issue I had with it too – Alon Eitan May 08 '16 at 16:40
  • @AlonEitan What do you think about my answer? Worth an answer or? – Praveen Kumar Purushothaman May 08 '16 at 16:40
  • @AnjaliMadas Have a try with named sessions and let us know what's happening... `:)` – Praveen Kumar Purushothaman May 08 '16 at 16:41
  • 1
    @PraveenKumar I'd give it a +1 :) And i did – Alon Eitan May 08 '16 at 16:42

1 Answers1

3

Generally sessions are stored in Cookies. So, when you are making Cross-Domain requests, Cookies are not shared. A simple fix would be using a proxy.php but now I got the best solution as to use named sessions.

Use the following code to get your sid:

<?php
  if (isset($_GET["sid"]))
    session_id($_GET["sid"]);
  session_start();
  header("Access-Control-Allow-Origin: *");
  header("Content-type: application/json");
  var_dump(session_id()); // Gives you the SID.

From the next time, use the sid as a GET parameter, and that will check the server session and resume the session.

Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252