In the login action I'm having the following code:
public function login($sEmail, $sEncryptedPassword, $bIsClear = true)
{
$manager = $this->getServiceLocator()->get('session_manager');
$manager->start();
Container::setDefaultManager($manager);
$this->auth = new AuthenticationService();
$this->auth->setStorage(new Session('FSP'));
$dbAdapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$this->authAdapter = new AuthAdapter(
$dbAdapter,
'fsp_user',
'email',
'password'
);
$this->authAdapter
->setIdentity($sEmail)
->setCredential($sEncryptedPassword);
$authAuthenticate = $this->auth->authenticate($this->authAdapter);
if ($authAuthenticate->isValid()) {
$user = $this->authAdapter->getResultRowObject();
$storage = $this->auth->getStorage();
$storage->write(
array(
'email' => $user->email,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'id' => $user->id
)
);
}
I have two problems with this code:
1) I'm saving the session in the database, and the session SaveHandler is configured in a service manager. I don't know if once I'm using Zend\Authenticate I should use the session manager too. In the documentation is saying that
"Unless specified otherwise, Zend\Authentication\AuthenticationService
uses a storage class named Zend\Authentication\Storage\Session, which,
in turn, uses Zend\Session."
So my first question is: can I configure the sessionHandler using just Zend\Authenticate or do I have to use the session manager?
2)I can't figured out how session storage is working in ZF. After login, the session data is not persisted in the DB. If I'm doing some debugging I get the following data:
$session = new Container("FSP");
//this returns the session data
var_dump($session->getIterator());
//this returns empty
var_dump($this->auth->getStorage());
//this returns null, but I do have a FSP named cookie with an Id, showing in Chrome's developer tool
$cookie = $this->getServiceLocator()->get('request')->getHeaders()->get('cookie');
$sessionId = $cookie->FSP;
var_dump($sessionId);
However, if I'm doing a refresh on the login (the login action is run again) the data from the previous session is wrote in the DB and not the data from the current one.
So the second question is, why the session data is not persisted in the database at login and at what step in the session instantiation process is the cookie with the session ID created?
Related
I am trying to create a route to programmatically assign a specific ROLE to current user. This is my attempt.
/**
* #Route("/role/assign/{role}", name="role_assignment")
*/
public function assign($role)
{
$session = $this->get('session');
$firewallContext = 'main';
$token = new UsernamePasswordToken(
'admin',
null,
$firewallContext,
array('ROLE_ADMIN')
);
$session->set('_security_'.$firewallContext, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$response = new JsonResponse([
'success' => 'true',
'user' => $this->getUser(),
]);
$response->headers->setCookie($cookie);
return $response;
}
User is always null, but I expected he become "admin" after page refresh.
I would strongly advice you against doing such things on production platforms. You will be better off properly configuring User Impersonation instead. It will save you the headache of having to manually do all of this.
If you really, really, want to go this way you could try the code below:
/**
* #Route("/role/assign/{username}/{role}", name="role_assignment")
*
* #param \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface $tokenStorage
*
* #return JsonResponse
*/
public function assign($username, $role, TokenStorageInterface $tokenStorage)
{
// NOTES:
// 1. Make sure you are using the same User class as the one configured in `security.yml`
// 2. Keep in mind the $username MUST exist and MUST have the role you are setting,
// because the UserPasswordToken is reloaded from the session upon page refresh which triggers a check in the user provider and that will hit the database. In other words, if the user doesn't have `ROLE_ADMIN` you will most-likely get logged out or see "AccessDeniedException".
// For more information check \Symfony\Component\Security\Core\User\UserProviderInterface::refreshUser.
$user = new \Symfony\Component\Security\Core\User\User($username, null, array($role), true);
// Create token
$firewall = 'main'; // This MUST MATCH the name in your security.firewalls.->main<- or authentication WILL FAIL!
$usernamePasswordToken = new UsernamePasswordToken($user, null, $firewall, $user->getRoles());
// You don't need to save the token via $session->save().
// You can directly use $tokenStorage, which will do that for you.
$tokenStorage->setToken($usernamePasswordToken);
// Pass authentication to client.
return new JsonResponse(['success' => 'true', 'user' => $user]);
}
If you are trying to authenticate for test cases, you can have a look at my answer here which shows how you can configure a client which can authenticate as any user with any role you set (the user doesn't even have to exist in the db). This works fine for me on 3.4 so it should still work for 4.0.
I am building a SOAP Web Service with Yii, and I am trying to manage the authentications through the Session ID, but it keeps changing on every request.
This is the code I have written:
class MessagingController extends CController {
public function login($username, $password) {
$user = User::model()->find('username=:username AND password=:password', array(':username' => $username, ':password' => $password));
if($user) {
$session = new Session();
$session->id = Yii::app()->session->sessionID;
$session->user = $user->id;
$session->start = date('Y-m-d H:i:s', time());
$session->duration = $this->sessionDuration; //Session duration is 1hr.`
return $session->save() ?
$this->generateResponse(0, 'Session initiated successfully.', array('SessionId' => $session->id, 'Timestamp' => $session->start, 'Duration' => $session->duration)) : generateResponse(-1, 'Server error. #S', null);
}
return $this->generateResponse(-1, 'Unknown User. #UU', null);
}
}
Config File:
'session' => array(
'autoStart' => true,
'timeout' => 1440,
'cookieMode' => 'allow',
),
I believe you have to specify in your SoapServer that the session should be persistent.
http://php.net/manual/en/soapserver.setpersistence.php
Since soap requests are stateless, each request goes without cookies and as such PHP by default will always create new cookie when starting new session. If you want to use the same session on SoapServer side across multiple client requests, you should set two things:
first ensure that you always send the same session cookie from your requesting server (via SoapClient). This is done by __setCookie():
$soapClient->__setCookie('PHPSESSID', $_COOKIE['PHPSESSID']);
second - as stated above - set soapserver persistence:
$soapServer->setPersistence(SOAP_PERSISTENCE_SESSION);
I am attempting to log in users with:
$login = Auth::instance()->login($this->request->post('username'), $this->request->post('password'), TRUE);
However it fails when trying to set the autologin cookie, with ErrorException [ Notice ]: Trying to get property of non-object when it gets to:
// Token data
$data = array(
'user_id' => $user->pk(),
'expires' => time() + $this->_config['lifetime'],
'user_agent' => sha1(Request::$user_agent),
);
// Create a new autologin token
$token = ORM::factory('User_Token')
->values($data)
->create();
// var_dump($token); // null
// Set the autologin cookie
Cookie::set('authautologin', $token->token, $this->_config['lifetime']);
If I var_dump($token) it says it is null. I have checked the database and it appears to be added correctly. My config has driver => 'ORM'. Logging in works if the remember me flag is set to FALSE. Why is $token not an object? Is there something I have missed?
I caused the error by overriding the create() method in class ORM_Base extends Kohana_ORM which then called the parent::create() but directed the user_token to the wrong create(). Fixed by removing the create() I added.
I'm logging in with the HybridAuth plug-in at the address = /cake/hybridauth/auth/google, then I use these details to look up the user on the database and log them in to the default CakePHP Auth like so:
$hybridauth = new Hybrid_Auth($hybridauth_config);
$adapter = $hybridauth->authenticate($provider);
$userprofile = $adapter->getUserProfile();
//look up user + register if not found
$this->loadModel('User');
$isUser = $this->User->find('first', array(
'conditions' => array(
'User.provider' => strtolower($provider),
'User.identifier' => $userprofile->identifier
),
'callbacks' => true
));
if(!$isUser){
//register the user
} else {
//update user with new credentials
$this->Auth->login($isUser["User"]);
//this doesn't work across the whole site,
//only this controller's "action" page
}
This all works fine, until I go back to my homepage at /cake/, where there seems to be no recognition of me having logged in - although on the controller's action page (cake/hybridauth/auth/google) I have the user logged into the Auth component and the above code seemed to work...
Any ideas what I'm missing please?
Many thanks.
I am using Elliot Haughin's twitter oauth library for codeigniter. It can be found here :
https://github.com/elliothaughin/codeigniter-twitter
I have the following code which authenticates a user with twitter and stores session details.
public function login() {
$this->tweet->set_callback(site_url(''));
$this->tweet->login();
$tokens = $this->tweet->get_tokens();
$user = $this->tweet->call('get', 'account/verify_credentials');
$u = $user->screen_name ;
$data = array(
'user' => $u,
'logged_in' => true
);
$this->session->set_userdata($data) ;
}
This is weird but the logged_in variable is saved whereas the user is not. I am not sure where i am going wrong.
have you include SESSION library or autoload it.
Update:
http://codeigniter.com/user_guide/libraries/sessions.html