2
votes

Using prefixes, I have separate sessions and logins for admins versus users. For example the AppController.php has:

    if ($this->request->prefix == 'admin') {

        $this->loadComponent('Auth', [
            'authenticate' => [
                'Form' => [
                    'userModel' => 'Admins',
                    'fields' => ['username' => 'email', 'password' => 'password']
                ],
            ],
            'loginAction' => [
                'controller' => 'Admins',
                'action' => 'login'
            ],
            'loginRedirect' => [
                'controller' => 'Admins',
                'action' => 'index'
            ],
            'logoutRedirect' => [
                'controller' => 'Admins',
                'action' => 'login',
            ],
            'storage' => [
                'className' => 'Session',
                'key' => 'Auth.Admin',              
            ],
        ]);

    } else {

        $this->loadComponent('Auth', [
            'authenticate' => [
                'Form' => [
                    'userModel' => 'Users',
                    'fields' => ['username' => 'email', 'password' => 'password']
                ],
            ],
            'loginAction' => [
                'controller' => 'Users',
                'action' => 'login'
            ],
            'loginRedirect' => [
                'controller' => 'pages',
                'action' => 'home'
            ],
            'logoutRedirect' => [
                'controller' => 'Users',
                'action' => 'login',
            ],
            'storage' => [
                'className' => 'Session',
                'key' => 'Auth.User',               
            ],
        ]);

    }

This is working fine in that users who visit example.com/admin get redirected to the admin login area, users who visit example.com get redirect to the user login area, and users can be logged into one, the other, or both simultaneously without interfering with each other.

The problem comes when I want admins to be able to "login as" another user. In CakePHP2 I was able to do this:

    AuthComponent::$sessionKey = 'Auth.User'; // solution from http://stackoverflow.com/questions/10538159/cakephp-auth-component-with-two-models-session
    $this->Auth->loginAction = array('admin'=>false,'controller'=>'accounts','action'=>'login');
    $this->Auth->loginRedirect = array('admin'=>false,'controller'=>'pages','action'=>'home');
    $this->Auth->logoutRedirect = array('admin'=>false,'controller'=>'accounts','action'=>'login');
    $this->Auth->authenticate = array(
        'Custom' => array(
            'userModel' => 'Account',
            'fields' => array('username' => 'number'),
        )
    );
    if (!$this->Auth->login($account['Account'])) {
        throw new NotFoundException(__('Could not login to account'));
    }

    return $this->redirect(array('admin' => false, 'controller' => 'getting_started', 'action' => 'index'));

And everything worked fine. But in CakePHP3 the AuthComponent::$sessionKey property doesn't appear to be accessible, instead I think I'm meant to use $this->Auth->config. But when I use this code:

public function loginas($id = null)
{

    $user = $this->Users->get($id, [
        'contain' => []
    ]);

    $this->Auth->config([
        'authenticate' => [
            'Form' => [
                'userModel' => 'Users',
                'fields' => ['username' => 'email', 'password' => 'password']
            ],
        ],
        'loginAction' => [
            'controller' => 'Users',
            'action' => 'login'
        ],
        'loginRedirect' => [
            'controller' => 'pages',
            'action' => 'home'
        ],
        'logoutRedirect' => [
            'controller' => 'Users',
            'action' => 'login',
        ],
        'storage' => [
            'className' => 'Session',
            'key' => 'Auth.User',               
        ],
    ]);

    $this->Auth->setUser($user->toArray());
    return $this->redirect([
        'prefix' => false,
        'controller' => 'pages',
        'action' => 'home',
    ]);     
}

I can successfully "login as", however it ALSO overwrites the user information for the existing admin session with the normal user details.

How can I get CakePHP 3 to leave the Auth.Admin session completely alone, and set up a new Auth session against the Auth.User session key (which happens to open in a new tab)?

2
How did you check to figure that the data has been overwritten? - ndm
I was debugging $this->Auth->user() to the screen, and what would happen is: - original tab as admin (in an admin prefix): click login as on user - new tab opens as user (not in admin prefix), all correct - in the original tab in the admin prefix, if I now reloaded the page, the userid would show as the user rather than the admin (so I was now logged into the admin area with a userid not an adminid) - sverreg

2 Answers

4
votes

OK I think I have this figured out, I needed to use $this->Auth->__set('sessionKey', 'Auth.User'); before calling $this->Auth->config().

public function loginas($id = null)
{

    $user = $this->Users->get($id, [
        'contain' => []
    ]);

    $this->Auth->__set('sessionKey', 'Auth.User');

    $this->Auth->config([
        'authenticate' => [
            'Form' => [
                'userModel' => 'Users',
                'fields' => ['username' => 'email', 'password' => 'password']
            ],
        ],
        'loginAction' => [
            'controller' => 'Users',
            'action' => 'login'
        ],
        'loginRedirect' => [
            'controller' => 'Pages',
            'action' => 'home'
        ],
        'logoutRedirect' => [
            'controller' => 'Users',
            'action' => 'login',
        ],
        'storage' => [
            'className' => 'Session',
            'key' => 'Auth.User',               
        ],
    ]);

    $this->Auth->setUser($user->toArray());
    return $this->redirect([
        'prefix' => false,
        'controller' => 'Pages',
        'action' => 'home',
    ]);     
0
votes

In AppController this code is working for me..

    use Cake\Event\Event;


    public function beforeFilter(Event $event){
          $this->Auth->sessionKey='Auth.Admin';
    }