I wanted to integrate the oauth2 server into my laravel 4.1 project. The password flow went pretty well but when writing the authorization code flow I encountered some strange problems with the sessions.
The request to generate leads to this function where filtered for logged in users
Route::get('security/authorize', array('before' => 'check-authorization-params|auth', function()
{
[...]
}));
Guests are redirected to a form to log in
Route::get('security/login', array('before' => 'guest' ,function()
{
return View::make('users.login');
}));
Wich leads to this route where the user should be logged in and redirected to the request he intended to do:
public function login()
{
$creds = array(
'email' => Input::get('email'),
'password'=>Input::get('password')
);
if(Auth::attempt($creds, true))
{
return Redirect::intended('/');
}
return Redirect::to('security/login');
}
The problem is, despite a positive Auth::attempt() I keep being redirected by the auth filter.
I made a few brief tests to check whats wrong by setting and reading session data wich never reached the next request, so i figured out i must have to do with my sessions.
Here's my session config file
<?php
return array(
'driver' => 'database',
'lifetime' => 120,
'expire_on_close' => false,
'files' => storage_path().'/sessions',
'connection' => 'mysql',
'table' => 'sessions',
'lottery' => array(2, 100),
'cookie' => 'laravel_session',
'path' => '/',
'domain' => null,
);
and here are some things I double checked:
database connection is correct and sessions show up in my table
session table fields have the right data types (id - varchar(255), payload - text, last_activity - int(11))
cookies get set
It turned out, that I did not set up the auth identifier in my user model correctly.
Changing it from this
public function getAuthIdentifier()
{
return $this->email;
}
to this
public function getAuthIdentifier()
{
return $this->id;
}
fixed everything.
Related
I have time in seconds when the session should end. If the user has not selected the checkbox "remember_me" - the session will last 2 hours. When the checkbox is selected - should last - 48 hours. I have a loginСontroller, where I react - to the login result and if the validation is successful and checkbox = "on" you need to change the session time. I tried to change by looking at the documentation, and spent a lot of time looking for a solution. Maybe someone can help me. Thank you very much in advance[enter image description here]
here is my file config/app.php
'Session' => [
'defaults' => 'php',
'ini' => [
'session.cookie_lifetime' => 7200,
]
],
and here is my loginController
`public function index()
{
$this->viewBuilder()->setLayout('main');
$this->set("title", "");
$this->set("description", "description");
$this->request->allowMethod(['get', 'post']);
$result = $this->Authentication->getResult();
// regardless of POST or GET, redirect if user is logged in
if ($result->isValid()) {
if ($this->request->getData('remember') == 'on') {
///// the solution should be here
}
$redirect = [
'controller' => 'Main',
'action' => 'index',
];
return $this->redirect($redirect);
}
// display error if user submitted and authentication failed
if ($this->request->is('post') && !$result->isValid()) {
$this->Flash->saved_error(__('Invalid email or password'));
}
}`
You most likely shouldn't do it that way, your controller code shouldn't have to know about such details if it can be avoided.
The authentication plugin ships with a cookie based authenticator that you can use in addition to the session authenticator, that way you can extend authentication beyond the default session lifetime, I'd suggest that you look into that instead.
$service->loadAuthenticator('Authentication.Cookie', [
'fields' => $fields,
'loginUrl' => $loginUrl,
'cookie' => [
// cookie expires in 2 days from now
'expires' => \Cake\Chronos\Chronos::now()->addDays(2)
],
]);
By default the authenticator looks up a field named remember_me, so either rename that in your template, like:
echo $this->Form->control('remember_me', ['type' => 'checkbox']);
or configure the authenticator's rememberMeField option with the custom field name that you're using in your form.
See also
Authentication Cookbook > Authenticators > Cookie Authenticator
I'm using this JWTAuth adapter to use JWT authentication instead of cookie-based auth in my CakePHP 2.8 app. It works great, except for one hitch:
Normally for one of my REST endpoints, I can use $this->Auth->user("id") to get the currently logged-in users' ID.
When I try to make a controller action accessible to non-members using $this->Auth->allow(), a problem occurs. If I do this, using $this->Auth->loggedIn() in the controller returns false, meaning I can not add additional logic for logged-in users.
When using standard cookie auth:
$this->Auth->user('id') is available in
Controller::beforeFilter().
$this->Auth->loggedIn() is true in
Controller::beforeFilter().
$this->Auth->user('id') is available in controller actions, public
and members-only.
$this->Auth->loggedIn() is true in controller actions, public
and members-only.
When using JWT auth:
$this->Auth->user('id') is null in Controller::beforeFilter().
$this->Auth->loggedIn() is false in
Controller::beforeFilter().
$this->Auth->user('id') is available in members-only controller actions, and null in public controller actions.
$this->Auth->loggedIn() is true in members-only controller actions, and false in public controller actions.
Is there any way I can get Auth to include information returned by the JWTAuth component on actions that have been made public by $this->Auth->allow()?
Example controller here:
public function visible(){
// This will always be false, even if a valid JWT token is sent
$this->set("loggedIn", $this->Auth->loggedIn());
}
public function members_only(){
// This will be unavailable if not logged in, and a true if logged in
$this->set("loggedIn", $this->Auth->loggedIn());
}
public function beforeFilter($options = array()){
parent::beforeFilter();
$this->Auth->allow("visible");
}
And for reference, my AppController::components array;
public $components = array(
'DebugKit.Toolbar',
'Auth' => array(
'authorize' => array(
'Actions' => array(
'actionPath' => 'controllers'
),
),
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email'),
'contain' => array(
'UserProfile',
)
),
'JwtAuth.JwtToken' => array(
'fields' => array(
'username' => 'email',
'token' => 'password',
),
'header' => 'AuthToken',
'userModel' => 'User',
),
),
'unauthorizedRedirect' => false
),
"Acl",
"RequestHandler",
"Session"
);
For stateless adapters authentication process is triggerd in AuthComponent::startup(). Component's startup() methods are run after Controller::beforeFilter(), that is why AuthComponent::user() doesn't return any info.
For other adapters when user is authenticated the identity info is stored in session. Getting that info doesn't require any authentication process which is why AuthComponent::user() give you the user info in case of standard cookie based auth.
I'm a bit late, but I found a solution to this problem, but (warning!) it involved updating the code for AuthComponent.
I took a copy of Lib/Controller/Component/AuthComponent.php and placed it under app/Controller/Component/AuthComponent.php.
I then added one line to the file:
public function startup(Controller $controller) {
$methods = array_flip(array_map('strtolower', $controller->methods));
$action = strtolower($controller->request->params['action']);
// One-line modification from the ordinary CakePHP file.
// This lets us have info on the logged-in user in public actions when using stateless auth.
$this->_getUser();
Voila, you can now access user info on the server while accessing a non-protected controller function with stateless auth!
I have an application based on CakePHP version 3.2.10. I'm totally new in CakePHP so sorry if it is a banal problem. In my application I use CSRF component and Auth component configured in this way:
$this->loadComponent('Auth', [
'authorize'=> 'Controller',
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email',
'password' => 'password'
],
'scope' => [
'Users.active' => 1,
]
]
],
'loginAction' => [
'controller' => 'Users',
'action' => 'login'
],
'logoutAction' => [
'controller' => 'Users',
'action' => 'logout'
],
'logoutRedirect' => [
'controller' => 'Pages',
'action' => 'index'
],
'unauthorizedRedirect' => '/', // $this->referer()
]);
and login action like
public function login()
{
$this->set('title', 'Logowanie');
$this->set('bodyclass', 'main-page');
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
if($user['blocked'] == 0) {
$this->Auth->setUser($user);
if ($this->Auth->user('role') == 'admin')
return $this->redirect(['controller' => 'Admin', 'action' => 'index']);
return $this->redirect($this->Auth->redirectUrl());
}
else{
$this->Flash->error('Konto zostało zablokowane przez administratora serwisu. Skontaktuj się z Biurem Obsługi.');
}
} else $this->Flash->error('Błędne dane logowania. Spróbuj ponownie.');
}
}
Now the problem:
Few days ago I changed server where application is running, and after changing it logging in stopped working. After clicking login there is a message CSRF Token cookie is missing. To test if the component is the problem i disabled csrf and try again then white screen appears and nothing happen if i refresh page i'm not logged in. I checked the working version and not working version and realized that Cake not store any cookies on new server, while on old there is everything ok and cookies are set.
After few researches i found out that not only cookies not work but all sessions. I try to dump $_SEESION but it shows something only right after calling $this->Auth->setUser($user), and nowhere else. So i look through some solutions and find that there is a setting in config/app.php to set up the session:
'Session' => [
'defaults' => 'php',
],
And read that when set in that way the session is stored in default php dir. So i changed it to cake(even make a dir sessions in tmp folder and added 777 permissions). But the problem was not solved. I have no idea why it not work. I tried setting cookiePath and other settings i Session config, but it still not work.
I think that this may be the server problem(permissions). So few words about servers: Old server where everything was working was my private server(i have full access), new server(or maybe virtual server/host) is on one of hosting companies(home.pl) where i have almost no privileges to configure.
Make sure you follow these steps:
//For Set
var $var = array('Cookie');
//For Write
$this->Cookie->write('YOUR DESIRED NAME', cookieData, $expires = null);
//For Read
$this->Cookie->read('YOUR DESIRED NAME');
Check in your Conroller code should be in src/Controller/AppController.php for below points
1) have you loaded cookie component properly in initialize() or beforeFilter() method?
2) do you have configured domain and path in your cookie configuration using $this->Cookie->configKey(), if Yes, then change domain to new domain or remove domain configuration.
3) delete cache folders for model and persistence from tmp folder
For more information about Cookie refer Document
Using Yii2 framework:
The code below creates an endless loop.
Can anyone please explain how I make the session data persist on redirect ?
I have checked and there is not data being transferred, but the session data is set inside searchuser correctly.
public function actionSearchUser()
{
$session = \Yii::$app->session;
$session->open();
$session->set('admin.currentuser.id', "This worked out ok");
return $this->redirect(['site/modify-user']);
}
public function actionModifyUser()
{
$session = \Yii::$app->session;
$session->open();
if( !($session->has('admin.currentuser.id')) )
{
return $this->redirect(['site/search-user']);
}
else return $this->render('modifyUser');
}
And here is where I setup my session:
'session'=>array(
'class' => 'yii\web\Session',
'name' => 'SESSIONNAME',
'timeout' => 86400,
'savePath' => '/path/to/sessions',
'useCookies' => true,
'cookieParams' => array(
'lifetime' => 86400,
'path' => '/',
'domain' => 'localhost',
),
),
My problem was the domain (I know, I'm stupid).
I have a custom domain (n099y.local) so I needed to change the cookie domain from localhost to n099y.local and everything was fine.
It was showing all the correct session data on the page until I went to another page when the data was again missing because the cookie domain did not match the domain I was on.
I'm currently working in a project I toke over after other people that started this build.
When I first started the project was two different subdomains x.domain.com and y.domain.com
now we are moving it to be one domain but two sites domain.com/x and domain.com/y.
earlier the login functionality was only available on the x subdomain but now I want users too be able to be logged in on both sites.
Each site has there on main controller (xController and yController) that both extends the xyController.
If I log in on the x-site everything works great but as soon as I go to domian.com/y
yii:app()->user->isGuest returns true
If I go back to domain.com/x im logged in.
I can't figure out why this is happening the PHPSESSID cookie is the same for both sites.
This is my class that extends CUserIdentity:
class UserIdentity extends CUserIdentity{
private $_id;
public function authenticate(){
$user=User::model()->findByAttributes(array('user_name'=>$this->username));
if($user === null){
$this->errorCode=self::ERROR_USERNAME_INVALID;
}else{
if($this->comparePassword($user, $this->password)){
/** Do some other checks here **/
$this->_id=$user->id;
$this->errorCode=self::ERROR_NONE;
return !$this->errorCode;
}
$this->errorCode=self::ERROR_USERNAME_INVALID;
}
return !$this->errorCode;
}
public function getId(){
return $this->_id;
}
}
and here is the part from the config file
'components'=>array(
'user'=>array(
'class'=>'WebUser',
// enable cookie-based authentication
'allowAutoLogin'=>true,
),
...
[EDIT] I found what the problem was, I had to set the id option in the config array to the same value in both configs, the id was not set in any of them before
Enable cookie-based authentication in your config:
'user' => array(
'allowAutoLogin' => true,
),
Than configure your session component:
'session' => array(
'savePath' => '/some/writeable/path',
'cookieMode' => 'allow',
'cookieParams' => array(
'path' => '/',
'domain' => '.yourdomain.com',
'httpOnly' => true,
),
),
Make sure that /some/writeable/path is really writable!
Finally, and this is the crucial bit with Yii (the above cookie configuration is generic PHP), the Yii application ID must be set in the config file:
'id' => 'yourdomain',
That's it!