I am using CakePHP's Auth-component for user-login data and want to associate the users_table with a user_details table. The association works, and if I manually get a user out it works fine, but is it possible to make the auth-component load in the associated table when logging the user in? so far I have tried this with no luck:
$this->loadComponent('Auth', [
'authorize' => ['Controller'],
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email',
'password' => 'password'
],
'contain' => ['user_details']
]
],
'loginAction' => [
'controller' => 'users',
'action' => 'login'
]
]);
Note the "contain" part - that is where I try to load associated table but with no luck?
Thanks.
contain has been deprecated in favor of 'finder'
so define a finder in your User Table
public function findDetails($query, array $options)
{
return $query
->contain(['UserDetails']);
}
and in the AppController
$this->loadComponent('Auth', [
'authorize' => ['Controller'],
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email',
'password' => 'password'
],
'finder' => ['details']
]
],
'loginAction' => [
'controller' => 'users',
'action' => 'login'
]
]);
https://book.cakephp.org/3.0/en/controllers/components/authentication.html#customizing-find-query
Related
I'm working on a Laravel 8 project that logs a user in through one of two Active Directory servers using LDAP Record 2.5 with a Users table in my DB (MySQL 8) just to have access to some basic info like name, email and a unique user id.
I got the initial part working - I get a successful login to the AD and my users table gets automatically synced with the Active Directory data. If I do a dd() right after the auth()->attempt() I will get what looks like a normally initialized User model and the relevant row in the users table has its remember_token field filled in.
But regardless of whether I pass a remember parameter or not there is no actual authentication - calling auth()->user() or Auth::user() returns a null anywhere except for the login method itself and the debug toolbar doesn't show a user model.
This is the code of my custom LoginController:
public function store(Request $request) {
$credentials = [
'mail' => $request->input('username').'#pio.rs',
'password' => $request->input('password'),
];
$remember = ($request->input('remember') == true) ? true : false;
auth()->shouldUse('pio');
if (auth()->attempt($credentials, $remember)) {
dd(auth()->user()); //returns working user model here
return redirect()->route('home');
} else {
auth()->shouldUse('voj');
if (auth()->attempt($credentials, $remember)) {
return redirect()->route('home');
}
}
}
And these are the settings in my config/auth.php file:
'defaults' => [
'guard' => 'pio',
'passwords' => 'users',
],
'guards' => [
'voj' => [
'driver' => 'session',
'provider' => 'voj',
],
'pio' => [
'driver' => 'session',
'provider' => 'pio',
],
],
'providers' => [
'voj' => [
'driver' => 'ldap',
'model' => App\Ldap\Voj\User::class,
'database' => [
'model' => App\Models\User::class,
'password_column' => false,
'sync_attributes' => [
'email' => 'mail',
'name' => 'cn',
],
'sync_existing' => [
'email' => 'mail',
//'operator' => 'ilike',
],
]
],
'pio' => [
'driver' => 'ldap',
'model' => App\Ldap\Pio\User::class,
'database' => [
'model' => App\Models\User::class,
'password_column' => false,
'sync_attributes' => [
'email' => 'mail',
'name' => 'cn',
],
'sync_existing' => [
'email' => 'mail',
//'operator' => 'ilike',
],
]
],
Any idea what I'm doing wrong?
Found the solution - just needed to call the auth middleware with middleware(['auth:pio,voj']) instead of just middleware(['auth'])
I'm strangling with a simple matter :
How to tell Cake to use a different Session configuration for different prefix (routes).
I have the main domain www.domain.tdl and I don't want the prefix couriers (www.domain.tdl/couriers) to use the same Session configuration to avoid Authentification problems : the main domain and prefix use different Authentification configurations.
So, in my App.php, the Session config is :
'Session' => [
'defaults' => 'cake',
'timeout' => 24 * 60, //in minutes,
'cookie' => 'app_bo',
// "cookiePath" => "/mrbo", (tried with or without)
'ini' => [
"session.name" => "MR_BO",
]
],
And I thought I could change the config in the AppController of the prefix :
src/Controller/Couriers/AppController.php
Configure::write('Session', [
'defaults' => 'cake',
'timeout' => 24 * 60, //in minutes,
'cookie' => 'app_courier',
"cookiePath" => "/mrcourier",
'ini' => [
"session.name" => "MR_COURIER",
]
]);
ini_set('session.cookie_name', 'app_courier');
ini_set('session.cookie_path', '/mrcourier');
ini_set('session.name', 'MR_COURIER');
Using only Configure::write did not work, that's why I added ini_set (seems like it update only internal CakePhp configuration).
By doing so, its works and not works. Indeed, I see that the domain and the prefix don't use the same, but when I tried to log in in the prefix page, nothing, it redirect to itself.
I think it's because CakePHP use Session internally before my settings in the prefix AppController.
EDIT
Here is the Auth component loading : (the one for the prefix is quit the same, only the controller model/controller change)
$this->loadComponent('Auth', [
'authorize' => ['Controller'],
'authenticate' => [
'Custom' => [
'passwordHasher' => [
'className' => 'Legacy',
],
'userModel' => 'Establishments',
'fields' => array('username' => 'login', 'password' => 'password'),
"salt" => "salt" // Relative field for SALT
],
],
'loginAction' => [
'controller' => 'establishments',
'action' => 'login'
],
'loginRedirect' => [
'controller' => 'pages',
'action' => 'dashboard'
],
'logoutRedirect' => [
'controller' => 'establishments',
'action' => 'login',
]
]);
In your auth configuration, use storage param to change Session settings. Use different key for each configuration
$this->loadComponent('Auth', [
'authorize' => ['Controller'],
'storage' => ['className' => 'Session', 'key' => 'Auth.Admin'],
/* ... */
]
);
I have a standard Form authentication declared in AppController.php:
$this->loadComponent('Auth', [
'authorize' => ['Controller'],
'authenticate' => [
'Form' => [
'scope' => ['Users.active' => 1]
]
],
'loginRedirect' => [
'controller' => 'Users',
'action' => 'account'
],
'logoutRedirect' => [
'controller' => 'Index',
'action' => 'index'
]
]);
Now I want an authentication based on api_key in a webservice. The doc, explains to do it like that:
$this->loadComponent('Auth', [
'authenticate' => [
'Basic' => [
'fields' => ['username' => 'username', 'password' => 'api_key'],
'userModel' => 'Users'
],
],
'storage' => 'Memory',
'unauthorizedRedirect' => false
]);
So now I wonder how to load the second authentication mechanism in my webservice. I tried to do that:
class DeviceconnectionsController extends AppController
{
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Auth', [
'authenticate' => [
'Basic' => [
'fields' => ['username' => 'username', 'password' => 'api_key'],
'userModel' => 'Users'
],
],
'storage' => 'Memory',
'unauthorizedRedirect' => false
]);
}
....
}
But Cake complains that I try to reload a different Auth Component.
So maybe the right way is to load both authentication mechanisms in AppController.php like below:
$this->loadComponent('Auth', [
'authorize' => ['Controller'],
'authenticate' => [
'Form' => [
'scope' => ['Users.active' => 1]
],
'Basic' => [
'fields' => ['username' => 'username', 'password' => 'api_key'],
'userModel' => 'Users'
],
],
'loginRedirect' => [
'controller' => 'Users',
'action' => 'account'
],
'logoutRedirect' => [
'controller' => 'Index',
'action' => 'index'
]
]);
But it seems incorrect as both authentication uses a different storage and unauthorizedRedirect setting.
How to do?
This question already has answers here:
Can Anyone Explain Laravel 5.2 Multi Auth with Example
(3 answers)
Closed 3 years ago.
Authentication Drivers / "Multi-Auth"
as prior to release of laravel 5.2 it is stated that multi auth suppots out of the box. but there is no any example codes showing how to authenticate using different drivers with routes. So I need help setting up the multi-auth using default laravel 5.2
Create two new models: App\Admin and App\User. Update config/auth.php:
return [
'defaults' => [
'guard' => 'user',
'passwords' => 'user',
],
'guards' => [
'user' => [
'driver' => 'session',
'provider' => 'user',
],
'admin' => [
'driver' => 'session',
'provider' => 'admin',
],
],
'providers' => [
'user' => [
'driver' => 'eloquent',
'model' => 'App\User',
],
'admin' => [
'driver' => 'eloquent',
'model' => 'App\Admin',
],
],
'passwords' => [
'user' => [
'provider' => 'user',
'email' => 'auth.emails.password',
'table' => 'password_resets',
'expire' => 60,
],
'admin' => [
'provider' => 'admin',
'email' => 'auth.emails.password',
'table' => 'password_resets',
'expire' => 60,
]
]
];
In kernel.php
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class
];
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
//\App\Http\Middleware\VerifyCsrfToken::class,
],
'api' => [
'throttle:60,1',
],
];
and in Route.php set below code and test
Route::get('/login', function() {
$auth = auth()->guard('admin');
$credentials = [
'email' => 'admin#gmail.com',
'password' => 'password',
];
if ($auth->attempt($credentials)) {
return redirect('/profile');
}
});
Route::get('/profile', function() {
if(auth()->guard('admin')->check()){
print_r(auth()->guard('admin')->user()->toArray());
}
if(auth()->guard('user')->check()){
print_r(auth()->guard('user')->user()->toArray());
}
});
Using the rajpurohit-dinesh example, we just need to finnish first step:
1:
Create an App\Admin model (on our app folder). Here is how should be your Authenticatable class.
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
Class Admin extends Authenticatable
{
//
}
2: Update config/auth.php.
return [
// This is the default guard used, not need to declare
// another guard here
'defaults' => [
'guard' => 'user',
'passwords' => 'user',
],
// Here we must to declare the guards, if we created the App\Admin
// class as first step, we don't need to create a custom guard
'guards' => [
'user' => [
'driver' => 'session',
'provider' => 'user',
],
'admin' => [
'driver' => 'session',
'provider' => 'admin',
],
],
// In this example we are using only 'eloquent' driver
'providers' => [
'user' => [
'driver' => 'eloquent',
'model' => 'App\User',
],
'admin' => [
'driver' => 'eloquent',
'model' => 'App\Admin',
],
],
'passwords' => [
'user' => [
'provider' => 'user',
'email' => 'auth.emails.password',
'table' => 'password_resets',
'expire' => 60,
],
'admin' => [
'provider' => 'admin',
'email' => 'auth.emails.password',
'table' => 'password_resets',
'expire' => 60,
]
]
];
3: To test it, we can use our app\Http\Route.php file:
Route::get('/login', function() {
$auth = auth()->guard('admin');
$credentials = [
'email' => 'admin#gmail.com',
'password' => 'password',
];
if ($auth->attempt($credentials)) {
return 'Success';
} else {
return 'Not Success';
});
Thanks for answer HoLiC, it's working right now but can you try to implement it with classes what Laravel's bring on start? You just have to add routes:
Route::controller('/auth', 'Auth\AuthController');
Route::controller('/password', 'Auth\PasswordController');
and create form in resources/views/auth/login.blade.php from my post above. After this you can use routes laravel.dev/auth/login and laravel.dev/auth/logout
Starter auth mechanism doesn't working good and its not compatibile with multi auth. If you check you can login via laravel.dev/auth/login but only user(theres no any way to setup in AuthController or anyplace to use admins) and logout action not working. If you check this trait Illuminate\Foundation\Auth\AuthenticatesUsers you will see that this mechanims is unuseful right now for example logout method not defines anywhere provider admin:
Auth::logout(); // not working logout should be smth like Auth::guard($provider)->logout();
I am using Auth component to check user is logged in.
Here is my AppController's initialize function
public function initialize()
{
parent::initialize();
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'username',
'password' => 'password'
],
'passwordHasher' => [
'className' => 'Md5',//My own password hasher
]
]
],
'loginAction' => [
'controller' => 'Dashboard',
'action' => 'login'
]
]);
}
Its working fine.But if I stay inactive for few minutes(like 3-5min) and go(click) to a link it sends me login page.It seems session time expired.
How or Where I can increase this time.
Auth component shares Session class
For Cakephp3
At config/app.php we can set the timeout.
'Session' => [
'defaults' => 'php',
'timeout'=>24*60//in minutes
],
For Cakephp2
in your Config/core.php
Configure::write('Session', array(
'defaults' => 'php',
'timeout' => 31556926 //increase time in seconds
));
Auth component shares Session class. For CakePHP 3 you can set session timeout at config/app.php like below:
'Session' => [
'defaults' => 'php',
'timeout' => 1440, /*24 hours*/
],