Customize Laravel auth Login - laravel

I need to customize the Login native code of the Laravel Authentication. I started by overrode some methods on LoginController such us credentials and validateLogin adding a field.
But I need to add some other checks, such us the possibility to join with an other table and other code, before to login the user but I didn't find solutions on internet.
I found some infos about the possibility to override the attemptLogin method or create a guard, but I didn't understand how do this.

In you LoginController you can just override the attemptLogin() any other method in AuthenticatesUsers trait depending on where your custom logic will make sense:
class LoginController extends Controller
{
use AuthenticatesUsers;
protected function attemptLogin(Request $request)
{
// add your logic here
}
}

Related

Laravel sanctum custom model

I'm using Laravel sanctum to authenticate my API, and I wanted to customize personal access token model so I did the following:
I created new model named PersonalAccessToken in App namespace.
I override model used in sanctum to be my new model by adding this line to my AppServiceProvider boot() method.
Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
but when I create a token it works fine and insert it into DB but this line throw exception
return new NewAccessToken($token, $token->id.'|'.$plainTextToken);
and that's because it's type hinted to be an instance of Laravel\Sanctum\PersonalAccessToken
how can I fix that
If you are not extending the default PersonalAccessToken that maybe your issue.
Instead of extending Model extend use Laravel\Sanctum\PersonalAccessToken
use Laravel\Sanctum\PersonalAccessToken as Model;
class CustomPersonalAccessToken extends Model
{
// Add you customisation here
}

How to influence execution's priority of the custom Request class?

As you might already know from the docs, Laravel's custom Request class (make:request using artisan) provides a possibility to keep validation rules inside of it. So, I have the following code's examples to describe the problem of the prioritization better:
api route
Route::post('/suggest', [SuggestionController::class, 'store'])
->middleware(['auth:sanctum']);
Request class
class SuggestionRequest extends FormRequest
{
public function authorize()
{
return $this->user() && $this->user()->hasRole('sales manager');
// return true;
}
public function rules() {...}
}
Here, I want to force my vendor middleware auth:sanctum (which checks if the current user has a token) to be executed before the SuggestionRequest class calls its own authorize method, because it doesn't make sense to validate the request's data and then check if the user is authenticated. Also, there's no need to have a quite similar logic in both places. Which way should I refactor my code? Are there any good approaches for it?

Controller constructor to check Auth middleware for two different guards

I have a dashboard view that shows certain contain depending on which user is viewing, whether it be an admin or just a regular user.
I can get my admins onto that page, but regular users aren't able to currently because of my middleware guard.
class DashboardController extends Controller {
public function __construct()
{
$this->middleware('auth:admin');
}
public function index()
{
return view('dashboard.index');
}
}
The following code checks on each DashboardController call for auth:admins, but I want regular users to access this too, is there a way to check the auth middleware twice like so?
$this->middleware(['auth:admin','auth']);
So ideally it will check if you're an admin or just a regular auth user.
Also on my view page, when accessing properties of an admin I'm using:
{{ Auth::user()->admin_username }}
Is this normal? I have an admin Model but I'm still accessing it via Auth::user() which feels strange to me, shouldn't it be Auth::admin()->admin_username
Accessing a particular page for users with differing roles is more suited for laravels gates and policy authorization mechanisms.
https://laravel.com/docs/5.5/authorization#writing-gates
These allow you to write fine tuned rules for each use case you have. Simple gates can be defined as closures within your application AuthServiceProvider. For example:
public function boot()
{
$this->registerPolicies();
Gate::define('access-dashboard', function ($user, $post) {
return auth()->check() && (auth()->user()->hasRole('admin') || auth()->user()->hasRole('regular'));
});
}
Then you can use the gate facade wherever necessary, for instance a controller method or constructor.
if (Gate::allows('access-dashboard', $model)) {
// The current user can access dashboard, load their data
}
Alternatively use the can or cant helpers on the user model directly.
if (auth()->user()->can('access-dashboard')) {
//
}
Of course, you can achieve similar via middleware, the advantage of using the above is you can authorize actions at specific points in your code as well as reusability.
As for for last question, as you have it written is correct.
{{ Auth::user()->admin_username }}
Auth::user() or auth()->user() simply returns the currently authenticated user, regardless of their role.
Policies will never work without auth middleware

Laravel get Auth variable for both - api token and session based authentication

I am using laravel 5.2.
Recently, I've updated Auth module to have session based authentication for web and api_token based authentication for external api calls.
Now, I am finding error in using Auth::id() and Auth::user() where I've used api_token based authentication. So that I am forced to use Auth::guard('api')->id() and Auth::guard('api')->user() methods instead.
Now, my question is, is there any common method that I can use for both irrespective of api_token based authentication or session based? What about auth()->user() and auth()->id()?
What if am I using the any method for both of the authentication? For example, methodA() is used within api_token based authentication as well as in session based too, how can I handle that case if I required to use Auth variable?
I think that controllers, that handle regular requests (through session-based authentication), should be separate from api controllers (token-based authentication). So, each controller would have responsibility over a single part of the functionality. Also, changes in api controller will not have side effect in session controller. Therefore, you can specify auth guard explicitly in each controller. Laravel requires specifying guard explicitly, otherwise default guard will be used. There is no way to make intelligent guess about what guard to use natively. Of course, you can make something like this:
public function action(Request $request)
{
$guard = $request->has('api_token') ? 'api' : 'session';
$authUser = Auth::guard($guard)->user();
//your code next
}
If you will go with separate controllers you can generalize common functionality into parent abstract controller. Note, in example below ChildControllers differs only by namespace.
Parent:
<?php
namespace App\Http\Controllers\Api
use App\Http\Controllers\Controller;
abstract class ParentController extends Controller
{
public function action(Request $request)
{
$authUser = Auth::guard($this->guard)->user();
//your code...
}
}
API controller:
<?php
namespace App\Http\Controllers\Api
use App\Http\Controllers\ParentController
class ChildController extends ParentController
{
protected $guard = 'api';
//your code...
}
Session Controller:
<?php
namespace App\Http\Controllers\Session
use App\Http\Controllers\ParentController
class ChildController extends ParentController
{
protected $guard = 'session';
//your code...
}

How to access AuthController?

As I need to apply custom login to AuthController ( adding a public method that will be called to alter the protected $redirectTo )
I can alter the access scope for $redirectTo, however, I don't want to break the framework.
So, how can I access AuthController ? isn't it singletone class?
if you are not using Laravel default AuthController then In routes you can tell/specify about the custom controller for your login/logout and register. here is the example
Route::get('/user/login', ['as'=>'user-login','uses'=>'Login\LoginController#getLogin']);
Route::post('/user/login', 'Login\LoginController#postLogin');
Route::get('/user/logout', ['as'=>'user-logout', 'uses'=>'Login\LoginController#getLogout']);
// Registration routes...
Route::get('/user/register', 'Login\LoginController#getRegister');
Route::post('/user/register', 'Login\LoginController#postRegister');
Note
Login\LoginController, 1st Login is Login directory same as Auth directory while 2nd one is controller same is AuthController

Resources