I have multi-authentication set up in my laravel app. I set up different guards and providers for admin, doctor and patient. I've also set up the redirects for the various guards in my config\auth.php.
The only issue i'm having right now is, I want doctors to login with a unique number called MDCN which is saved to the database table instead of email. Please how do i customize the login for the doctors?
Ps: I've also set up the models for each, and i use laravel default auth.
my guard:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'admin-api' => [
'driver' => 'token',
'provider' => 'admins',
],
'doctor' => [
'driver' => 'session',
'provider' => 'doctors',
],
'doctor-api' => [
'driver' => 'token',
'provider' => 'doctors',
],
],
and provider:
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
'doctors' => [
'driver' => 'eloquent',
'model' => App\Models\Doctor::class,
],
],
In the App\Http\Controllers\Auth\LoginController you can override a method which returns by what fields the authentication should be checked and there you can pass the MDCN if you're logging a doctor:
protected function credentials(Request $request)
{
return $request->only('MDCN', 'password');
}
i finally solved this, thank to Alex Curtis.
In order to do this, you need to customize each model to tell it what you want to use to login.
So on any model that you want to log in with a username instead of an email you need to add this block of code to the model:
public function username()
{
return 'username';
}
And just make sure that the value you return (username in this example) matches the column name in that model's table that has the identifier you are looking to use.
Obviously you would also want to make sure you have a column in the DB to hold this data, you want it to be mass-assignable (by customizing the $fillable array in the model) and you also want the column to be indexed and unique.
To get this you want to create the column in a migration that looks like this:
$table->string('username')->unique();
This will make a unique index for that column.
The default is email, so if you are using email then you don't need to worry about this, but any model using something other than email will need this change made to that user type's model.
Related
I am upgrading a legacy application.
I am using Laravel 8 without ORM with DB first approach since the DB is already there.
I want to use
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
return redirect()->intended('shop');
}
When I am configuring auth.php I saw inside the providers 'driver' => 'database' was commented. I want to use auth.php providers like following
'providers' => [
// 'users' => [
// 'driver' => 'eloquent',
// 'model' => App\Models\User::class,
// ],
'users' => [
'driver' => 'database',
'table' => 'shop_users',
],
]
Is there any way I can map the user name password like following
'providers' => [
// 'users' => [
// 'driver' => 'eloquent',
// 'model' => App\Models\User::class,
// ],
'users' => [
'driver' => 'database',
'table' => 'shop_users',
'username' => 'email', //Mapping auth username to table column
'password' => 'password' //Mapping auth password to table password
],
]
Make sure this model call is extended Authenticatable
we need to add a new function inside app/Http/Auth/LoginController.php like below:
public function username(){
return 'email'; // this string is column of shop_users table which we are going use for login
}
I use the built-in "Remember me" functionnality of Laravel 5.8. I checked the cookies and saw the remember-me cookie expires in about 5 years. That is way to long and I would like to shorten it. As Laravel automaticly creates the cookie, I don't have the hand on it. How can I do this ?
The remember me duration can be overridden by overriding the AuthenticatesUsers trait. You could add the following code to LoginController that overrides the trait in the following controller:
protected function sendLoginResponse(Request $request)
{
$customRememberMeTimeInMinutes = 10;
$rememberTokenCookieKey = Auth::getRecallerName();
Cookie::queue($rememberTokenCookieKey, Cookie::get($rememberTokenCookieKey), $customRememberMeTimeInMinutes);
$request->session()->regenerate();
$this->clearLoginAttempts($request);
return $this->authenticated($request, $this->guard()->user())
?: redirect()->intended($this->redirectPath());
}
An alternative is to invalidate the remember me session by setting the remember_token in the users table to an empty value.
Example:
$user = Auth::user();
$user->remember_token = null;
$user->save();
This is (at time of writing) so much easier with Laravel 8 (and likely earlier).
Just add the key remember to the appropiate guard in your config/auth.php file. In this example I have a custom guard called customGuard
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'customGuard' => [
'driver' => 'session',
'provider' => 'users',
'remember' => "10080" //Number of minutes the "remember me" option works for.
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
You can set the remember me cookie duration by adding 'remember' => 43800 in the config in config/auth.php
Just change:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
to:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
'remember' => 43800 // Set remember me duration here (minutes)
],
],
Note: The 'remember' key is a mandatory keyword, because it will be read by laravel in Illuminate\Auth\AuthManager namespace
I gotta problem with laravel Auth multi guard technology,
here is my config file
'defaults' => [
'guard' => 'admin',
],
'guards' => [
'admin' => [
'driver' => 'session',
'provider' => 'user',
],
'front' => [
'driver' => 'session',
'provider' => 'front',
],
],
'providers' => [
'admin' => [
'driver' => 'eloquent',
'model' => App\Modules\Admin\Models\User::class,
],
'front' => [
'driver' => 'eloquent',
'model' => App\Modules\WebUser\Models\WebUser::class,
],
],
The problem is that when I try to login by using front guard with id (primary key) like this Auth::guard('front')->loginUsingId(1); it returns me null, when I do like this Auth::loginUsingId(1); it logs me in, the this is that is working only with default guard, when I change defaults it works, but when trying to use a guard to login which is not set as default, then it does nothing. Any ideas why? May be I am missing something or what
According to how laravel works, this
Auth::guard('front')->loginUsingId(1);
will always return null. But trust me the Auth helper is working perfectly here.
To check if the user logged in or not
return Auth::guard('front')->user();
That will make a lot of sense once you see the output above.
Then you execute this:
Auth::guard('front')->loginUsingId(1);
You has been successfully logged in. You can test it with:
Auth::guard('front')->id();
If you try testing
auth()->id();
you will get 'null', because it's checking only default guard
You can try this solution:
Auth::guard('web')->loginUsingId(1);
$user=Auth::user();
$user->created_at=date('Y-m-d H:i:s');
$user->save();
I have multiple entities in my application that need to be authenticated. So I defined multiple guards to do so:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'customers',
],
'customer' => [
'driver' => 'passport',
'provider' => 'customers',
],
'partner' => [
'driver' => 'passport',
'provider' => 'partners',
],
'admin' => [
'driver' => 'passport',
'provider' => 'admins',
],
],
Then in my Login controllers I have the following condition:
if (Auth::guard('admin')->attempt(['email' => $email, 'password' => $password])) {
...
...
}
when I try to do so (even though it's written in the docs) I get an error telling me that "method attempt does not exist".
So I try defining the guard method on the controller (also like the docs) like this:
protected function guard()
{
return Auth::guard('admin');
}
authentication still doesn't work with the right credentials (I tried to check what guard the Auth facade was using before the attempt using dd(Auth::guard()) and it was the default web guard.
I tried removing the web guard from the default guards array in auth config. didn't work.
I also tried config:clear and rerunning the server but nothing worked!
I am out of ideas. I know that I can write my own simple login, but why reinvent the wheel, and I was following the docs to the letter. help.
Please, can anybody explain how to implement multiple authentication guards in Lumen framework? Currently, I have two authenticatable models: Users and Clients. I'm using a custom implementation of JWT. A User has client_id and user_id fields in their token payload. While a Client only has client_id. Based on this I need to determine who came to me: client, user or guest (without a token).
auth.php
'guards' => [
'client' => [
'driver' => 'token',
'provider' => 'clients',
],
'user' => [
'driver' => 'token',
'provider' => 'users',
],
],
'providers' => [
'clients' => [
'driver' => 'eloquent',
'model' => App\Client::class,
],
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
],
AuthServiceProvider.php
public function boot()
{
$this->app['auth']->viaRequest('token', function ($request) {
$access_token = HelperClass::getTokenFromHeader($request->headers->get('Authorization'));
if ($access_token) {
$tokendata = JWT::decode($access_token, getenv('TOKEN_SECRET'), array('HS256'));
if ($tokendata->user_id) {
return User::find($tokendata->user_id);
}
return Client::find($tokendata->client_id);
}
});
}
routes.php
$app->get('/api/{item_id:\d+}', ['middleware' => 'auth:user', 'uses' => 'App\Http\Controllers\ItemController#get']);
I want to allow only Users to access this route, but Clients successfully pass this middleware too: Auth::check() returns true and Auth::user() returns an instance of App\Client 😕
Another situation: what if for some routes I want to allow both: clients and users. For another routes - guests, clients and users.