1

I am using PhalconPHP, and trying to implement an authentication service. My front-end is an AngularJS 5 application that utilizes this service that is on a subdomain. (My front end is found at www.MyWebsite.com, and my service is found at service.MyWebsite.com) So far I have implemented the following method to start my session.

$di->setShared('session', function () {
    $session = new Session();
    $session->start();
    return $session;
});

Then, I call my loginUser method when the user posts their username/password to the service

public function loginUser(array $userData){
    $username = $userData['username'];
    $password = $userData['password'];
    $user = Users::findFirst(
        [
            'conditions' => '(username = :username:) AND password = :password:',
            'bind' => [
                'username'    => $username,
                'password'    => $password,
             ],
             'columns' => ['users_id AS id, first, last, username, email']
        ]
    );
    $this->_registerSession($user);
    return $user->toArray();
}

After a user attempts login, I stash the username and user ID into the session using the _registerSession($user) method.

private function _registerSession($user){
    $this->session->set(
        "auth",
        [
            "id" => $user->id,
            "username" => $user->username,
        ]
    );   
}

At this point, the user is able to successfully log in, as I am able to return the users ID, first and last name, username, and email, with the username and ID stored in my sessions auth configuration.

The issue that I have is that when I refresh my page, the User gets logged out.

The first thing I figured was that since my Angular app is an SPA, so refreshing the page will drop the current global variable I have set to store information on the current user. So, in order to fix that, I think I need to re-pull the information from the server based on the session.

So, I've implemented a method for getCurrentUser()

public function getCurrentUser(){
    $id = $this->session->auth["id"];
    if($id == null){
        return null;
    }
    $user = Users::findFirst(
        [
            'conditions' => 'users_id = :id:',
            'bind' => [
                'id'    => $id,
            ],
            'columns'    => "users_id AS id, first, last, username, email",
        ]
    );
    $this->_registerSession($user);
    return $user->toArray();
}

And when I test this using Postman, I am able to post to the login endpoint, and then anytime in the next 30 minutes if I make a call to getCurrentUser, I end up getting my values back.

BUT when I try to do this in the AngularJS app, I always get a null value on $id which tells me that it's not able to pull/doesn't see the auth in the session variable.

I've verified that the PHPSESSIONID being set in the cookies isn't changing, so the sessionID should still be the same... So why can't it pull that ID from the existing session in the Angular app, but it can when I make calls directly from PostMan?

EDIT Someone mentioned that it may be due to a CORS. They deleted their answer, but just to show my setup for that, here is the index file where I am attaching certain headers

if (isset($_SERVER['HTTP_ORIGIN'])) {
    // Decide if the origin in $_SERVER['HTTP_ORIGIN'] is one
    // you want to allow, and if so:
    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');    // cache for 1 day
}

// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
        // may also be using PUT, PATCH, HEAD etc
        header("Access-Control-Allow-Methods: GET, POST, OPTIONS");         

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
        header("Access-Control-Allow-Headers:{$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
    exit(0);
}

It may still have something to do with CORS, but from my limited knowledge I don't see that being the case.

Chris Hobbs
  • 745
  • 2
  • 9
  • 27

2 Answers2

1

Are you sure that angular 5 is making requests with withCredentials: true ?

Juri
  • 1,369
  • 10
  • 16
  • Nope, I'm not sure on that at all. I vaguely remember that coming up in my Googling, but never really gave it a try. I'll give it a shot when I'm home from work. Do you have a quick explanation as to what that does?? – Chris Hobbs Oct 11 '18 at 13:11
  • Simply sends angular requests with cookies. You can check this answer https://stackoverflow.com/a/47305611/4035199 – Juri Oct 11 '18 at 13:26
0

First try to get the session id: in getCurrentUser() use:

     $id = $this->session->get('auth');
     if (isset($id['id'])) {
         $user = ...

Also, in loginUser don't forget to bind username as email parameter as well.

a_byte_late
  • 131
  • 5
  • For the email, I stripped out a lot of the extras (try catch for error handling, email login, etc), but I'll update that in the original question. As for the session id, the value stored in auth["id"] is actually the user ID. This also works fine in Postman (I am able to post to my login method, and then if I do a get on my getCurrentUser method 10 min later, I get the expected results back. This only fails when I am running from my localhost or deployed site, and it doesn't have an error message because it's reading the ID (and Auth for that matter) as null – Chris Hobbs Oct 11 '18 at 13:09
  • Could you share the code of the controller called when refreshing the page please? – a_byte_late Oct 11 '18 at 13:39