Laravel - using Google 2FA to protect all views - laravel

I'm working on my first Laravel project and have implemented 2FA according to this tutorial but unfortunately, the 2FA mechanism created is attached only to HomeController.
So if a user tries to access www.thingy.com/something from an unauthenticated state, they enter email and password as usual and then get directly to /something without the 2FA prompt appearing.
My first thought was adding the middleware bit to every __construct() function in each of my resource controllers, but they don't already have a __construct() function (can I add one anyway?) and even if that worked, it doesn't seem like the right way of doing it.
I also considered adding it to Controller itself since that's what every other controller is based on, but of course I wouldn't want 2FA required for non-authenticated views too (just register, login etc really because the site requires a login to use).
What's the correct way of doing this?

You can add the middleware to a group of routes in your routes/web.php file.
Route::middleware('2fa')->group(function () {
// All routes here will go through the "2fa" middleware
});

Related

Laravel 9 - How to prevent showing login page after user is logged-in and hit browser back button

How can I ensure that as soon as the user is logged-in in Laravel-9 he can no longer go to the login page via browser back button?
I searched the internet for solutions. I have read in several places that it is not possible or that I have to use Javascript.
Just to be sure, I have decided to post my question here and I hope you can help me.
Is there any way to do this? If the solution is with javascript, how can I solve that with javascript?
Thanks
if you open guest Middleware /app/Http/Middleware/RedirectIfAuthenticated.php in your project, you can see the handle function with this condition:
...
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
...
It means that after login to the site if users try to go to the login page, the browser redirects the page to the HOME address. So users cannot access the login page after logging into your site.
finally, in your \routes\web.php file, you must apply guest Middleware on your register route in this way:
Route::get('register',[RegisterController::class,'create'])->middleware('guest');
Note: you can edit HOME address from the /app/Providers/RouteServiceProvider.php file.
This page lists several ways you could try to disable the back button via javascript, but none are guaranteed.
By default Laravel 9 has the RedirectIfAuthenticated middleware under App\Http\Middleware which checks if the user is logged in Auth::guard($guard)->check() and if they are they are taken to the /dashboard url otherwise they are not. The Middleware is registered as 'guest' in the $routeMiddleware array inside Kernel.php, this means that you can apply guest middleware to all routes that you do not need be accessed by logged in users.

Laravel: is there an easy way to force login?

I want to implement user authentication (require login to visit any page) for a Laravel project (Laravel 7.x/8.x) that is currently open to any visitor without login. With Auth::routes() in web.php, every thing works as expected with respect to login process if a user accesses or is redirected to the login page.
Now I'm wondering if there's a straight forward and simple mechanism that will redirect a user to the login page if the user is not logged in when accessing any page of the project without having to modify the controller or view of each page. Specifically what I'm looking for is something that I can set in a config file, e.g. config/auth.php, say, 'force_login' => true/false, so if 'force_login' is set to true, the system would automatically check whether or not a user is logged in when the user access any page and redirect to the login page if the user is not logged in, and if 'force_login' is set to false, the system would bypass the authentication process all together. Such kind of mechanism may already exist, but I found no mention of it when I searched around online. I appreciate any suggestions/hints. Thanks.
Yes, youu need to use the auth middleware on all the routes that you want to forced be logged, or tou could only group them in one.
// Auth is required to acces these routes
Route::middleware(['auth'])->group(function () {
Route::get('/home', 'HomeController#index');
Route::get('any_route', 'AnyController#index');
...
});
// Auth is not required
Route::get('/', function () {
return view('welcome');
});

Is it safe to delete the default route in api.php in Laravel 8?

I installed Laravel 8 and found the following route in routes/api.php.
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
I will create my own APIs which accept post and return json.
Should I remove the default sanctum route?
Is it safe to delete it? Or is it dangerous if I don't delete it?
I think it is dangerous if someone accesses /api/user. I don't know what it is.
I think it is dangerous if someone accesses /api/user. I don't know
what it is.
Yes it is good to remove this example route. On the other hand. Only authenticated User can see the userlist. If you are the only auth user in your application it not so much important if you forget to remove this route.
You can safely delete it. They just included it as an example or not to present you with an empty routes/api.php (not sure which).
Edit: Accessing /user will show the user associated with the bearer token. Sanctum's tokens aren't dependent on the /user route however.
Sacntum is cookie-based session authentication service. This is just an example route that will return the user data if he is logged-in. You can remove it safely without any issues.
It is completely safe to use as well as the user will only be able to access this route if he is already logged in and will only get his user information back not of all the users.

Laravel route in multiple middelwares

I want to have the same route within the auth:api middleware, and also out of it.
Right now, if I include it in both, only the one out of the auth:api is taken into consideration, even if the user is logged in.
Is there a way that if the user is logged in it goes to auth:api and if not it goes out of any middleware?
The reason to do this is that if the user is logged in, I want to access user information, and for that it needs to go through the auth:api.
As long as you're including the token in the request, you will be able to get access to the current User.
Out-of-the-box, Laravel will set the default guard to be web. When you place routes under the auth middleware it will set the default guard to be whatever is passed to the middleware i.e. when you have auth:api it will set the default guard to be api for that request.
If you want to be able to access the User without it being under the auth:api middleware, you will simply need to be explicit with what guard should be used e.g.
auth('api')->user(); // or Auth::guard('api')->user();
The same applies for check():
auth('api')->check(); // or Auth::guard('api')->check();
or if you're using the Request object:
$request->user('api'); // or request()->user('api');
It 's not possible to have multiple same routes in your application and work independently. Laravel will match the first one that it find in your routes map.
Create one route and check for authentication in your controller.
if (Auth::check()) {
// The user is logged in...
}

Laravel 5.3 Ajax Login Customize Credentials

I am able to login via Ajax in Laravel 5.3
This is easily accomplished by making a post request to the login route with the proper parameters.
However, for my application, I am designing two ways for a user to be logged in - via the traditional email/password combination that Laravel already supports, and via an access code that would be distributed and allow the possessor of said code to login without an email/password combination. There is no "registration" in my app, there is just different levels of authentication.
Anyway, in /vendor/laravel/framework/src/Illuminate/Foundation/Auth I am editing the AuthenticatesUsers.php and understand that this function specifically handles the login attempts:
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->has('remember')
);
}
My question is, how can I change the success of attempt() based on the content of the request?
In other words, if someone is sending an ajax access code it shouldn't be tested against an email/password combination, as it would obviously fail. Similarly, if they are sending an ajax with email/password parameters, it shouldn't be tested against the list of available access codes.
Am I on the right track? Where in Laravel can I go to make the Auth::attempt() contingent on request parameters?
I will not advice to edit a framework file.
You should rather write a middleware to handle identification of the type of authentication user is requesting for, before sending it to the controller. In your middleware,
public function handle($request, Closure $next)
{
// check if the request has access_code
$request->attributes->add(['using_access_code' => $request->has('access_code')]);
return $next($request);
}
And in your controller, you can check for positive test on this request parameter that we newly added (you can of course do this inside controller directly, but I personally like middleware to handle this because there are chances that you may want to add more functionality)
In your controller, if using_access_code is false, proceed with attempt() login, else, retrieve the user using access_code and manually authenticate the user using Auth::login($user). Let me know if you are unclear.

Resources