authenticates OK, next call - not authenticated

There are a number of threads in this forum covering an apparently successful login which disappears on the next call from browser to webserver. Causes are various, such as the identity object not implementing \yii\web\IdentityInterface

and incorrect configuration in web.php components. I’ve checked my code and can’t see any of those problems. Like others, hours have been spent, so I suggest that Yii needs to report problems with authentication a bit better - especially as authentication is often where one starts with a new app. (I have some Yii 1.1 apps running, this is my first Yii2 app).

I want session based login (with no autoLogin, i.e. no persistence between sessions). All PHP calls are XHR calls, the app loads index.html.

from web.php:


'user' => [

   'identityClass' => 'app\models\Brokers',

   'enableAutoLogin' => false,

   'enableSession' => true,

],

The Brokers class includes:


namespace app\models;


use Yii;


class Brokers extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface 

{

    public static function findIdentity($id)

    {

        return static::findOne(['dbBrokerNo' => $id, 'dbRejectBroker'=>0]);

    }


    public static function findIdentityByAccessToken($token, $type = null)

    {

        throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');

    }


    public static function findByUsername($username)

    {

            return static::findOne(['dbBrokerCode' => $username, 'dbRejectBroker' => 0]);

    }


    public function getId()

    {

        return $this->dbBrokerNo;

    }


    public function getAuthKey()

    {

        throw new NotSupportedException('"getAuthKey" is not implemented.');

    }


    public function validateAuthKey($authKey)

    {

        throw new NotSupportedException('"validateAuthKey" is not implemented.');

    }


    public static function tableName()

    {

        return 'Brokers';

    }

With the rest as generated by gii.

Below is my login Class, the "ping" action is used to demonstrate the problem - identity etc is null


namespace app\controllers;


use Yii;

use yii\filters\AccessControl;

use yii\web\Controller;

use yii\filters\VerbFilter;

use app\models\Brokers;

use yii\web\User;


use yii\helpers\Json;


class LoginController extends AjaxController

{

    public function behaviors()

    {

        return [

            'access' => [

                'class' => AccessControl::className(),

                'only' => ['logout','login','ping'],

                'rules' => [

                    [

                        'actions' => ['logout'],

                        'allow' => true,

                        'roles' => ['?'],

                        'verbs' => ['POST']

                    ],

                    [

                        'actions' => ['login'],

                        'allow' => true,

                        'roles' => ['?'],

                        'verbs' => ['POST']

                    ],

                    [

                        'actions'=>['ping'],

                        'allow'=>true,

                        'roles'=>['?'],

                        'verbs' => ['POST']

                    ]

                ],

                'denyCallback' => function ($rule, $action) {

                    throw new \Exception('You are not allowed to access this page');

                }

            ]

        ];

    }


    public function actions()

    {

        return [

            'error' => [

                'class' => 'yii\web\ErrorAction',

            ]

        ];

    }


    public function actionLogin(){

        $returns = [];

        

        $session = Yii::$app->session;

        $session->open();

        

        $user = \app\models\Brokers::findByUsername( $this->json->username );

       

        if( $user && $user->dbPassword === $this->json->password ) {

            Yii::$app->user->login( $user ); // $this->rememberMe ? 3600 * 24 * 30 : 0

            $returns[ 'accessLevel' ] = $user->dbAccessLevel;

            $returns[ 'getid' ] = Yii::$app->user->getId();

            $returns[ 'identity' ] = Yii::$app->user->identity;

        }

        $this->returns( $returns );

    }

    

    public function actionPing(){

        $returns = [

            'getid'=>Yii::$app->user->getId(),

            'id' => Yii::$app->user->id,

            'identity' => Yii::$app->user->identity

        ];

        $this->returns( $returns );

    }


    public function actionLogout(){

        Yii::$app->user->logout();

        $this->returns();

    }


}

and the class being extended by LoginController is:


namespace app\controllers;


use Yii;

use yii\web\Controller;

use yii\helpers\Json;

use yii\base\InvalidConfigException;


class AjaxController extends \yii\web\Controller {

    

    public $json;

    

    public function beforeAction($event)

    {

        $this->enableCsrfValidation = false;

        $this->json = Json::decode(file_get_contents("php://input"), false);

        header('content-type: application/json');

        return parent::beforeAction($event);

    }

    

    public function returns( $returns = [] ) 

    {

        $returns['isAuthenticated'] = ! Yii::$app->user->getIsGuest();

        echo Json::encode ( $returns );   

    }

}

Well, nobody was going to be able to help me with this, as I left out an important detail.

There is nothing wrong with the code I posted. It works.

What I omitted was that the XHR calls are cross-domain, and I had not covered off cookies in the headers, here they are

header(‘Access-Control-Allow-Origin: <i can’t post links>’);

header(‘Access-Control-Allow-Headers: content-type’);

header(‘Access-Control-Allow-Methods: post’);

header(‘Access-Control-Allow-Credentials:true’);

It was the last of these that was missing, that prevented the PHPSESSID cookie from reaching the server.