Why does Laravel skip my if-statement in Middleware? - laravel-5

I have created a Middleware to check if users with google2fa_enabled = 1 have a google2fa_secret and when they don't, they need to create one.
In the Middleware, I have defined the handle function with an if-statement and when true, it redirects the user to /2fa/create. It didn't work, so I made the if-statement like if(true), but the user is not being redirected. When I replace the return statement after that with return redirect('/2fa/create'), it does redirect, so the middleware is used (also confirmed with the Laravel debugbar)
The Middleware itself:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class checkTwoFactor
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(true){
redirect('/2fa/create');
}
return $next($request);
}
}
And the routes:
Route::get('/', function () {
return view('layouts/master');
})->middleware(['auth', 'check2fa']);
I expect the user to be redirected to /2fa/create at all times (and later on, if user is logged in, has google2fa_enabled = 1 & google2fa_secret == "")

Oops, I found the mistake already.
I need a return statement in that if-statement to work, so redirect() had to be return redirect()

Related

Laravel 8: GET params can't be accessed in Middleware's Request's inputs

I have defined this route in the web.php route file:
Route::get('/middleware_test_user_project_change/{pro_id}/{projet_id}', function ($pro_id, $projet_id) {
return 'test';
})->middleware('user.project.change');
I have defined this handle function in my middleware (which I've added into the kernel with the following entry: 'user.project.change' => \App\Http\Middleware\CheckUserProposition::class):
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use App\Models\User;
class CheckUserProposition
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle(Request $request, Closure $next)
{
$projet_id = $request->input('projet_id');
$pro_id = $request->input('pro_id');
return $next($request);
}
}
However, both $projet_id and $pro_id return NULL when I access the following URL: https://XYZ/middleware_test_user_project_change/1/1
As I've correctly set up the middleware and the routes parameters (which are, finally, GET variables), why can't I use them in my middleware as request inputs?
Route parameters are not part of the 'inputs'. They are a separate thing; this is why you don't see them when you get all the inputs with $request->all().
If you want a route parameter you should probably explicitly ask for it:
$request->route('projet_id');
$request->route()->parameter('projet_id');

Laravel multiple parameters in Route middelware not working

I have problem that using multiple parameters in my Route::middleware isn't working for me. I am trying to assign a specific route only accessible for a superuser and admin role.
When I just use:
role:superuser
it works fine, but when I add a second parameter like:
role:superuser,admin
it fails when I assign myself the admin role but still works for the superuser role.
I am confused so any help would be appreciated!
Here is my RoleMiddleware:
namespace App\Http\Middleware;
use Closure;
class RoleMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string $roles
* #return mixed
*/
public function handle($request, Closure $next, ...$roles)
{
$user = $request->user();
if ($user && $user->isSuperuser($roles)) {
return $next($request);
}
return redirect('/home')->withError('U heeft niet de juiste rechten!');
}
}
Here is my isSuperuser method in my User model:
public function isSuperuser(...$roles)
{
if ($roles) {
return $this->roles == $roles;
}
return $this->roles;
}
Last but not least my routes/web code for the middleware:
Route::get('/users', 'UsersController#index')->middleware(['role:superuser,admin']);
Btw: the method is called 'isSuperuser' but that's just a name. It also has to accept the admin role at some point.
use | instead of , like this:
Route::get('/users', 'UsersController#index')->middleware(['role:superuser|admin']);

Laravel how to remove url query params?

I request api to check user , and the backurl will add a query param token like this :
www.test.com?store_id=2&token = 123
I want to show this
www.test.com?store_id=2
I handle it in middleware , I wish there is a mothod to remove token before return $next($request)
but I didn't find the method. And I can't just use some method to delte this params and redirect , it will make a redirect loop.
if there is no better method, maybe I will create a new method in LoginController to remove token and redirect to where the page I from.
You can have some sort of global middleware:
class RedirectIfTokenInRequest {
public function handle($request,$next) {
if ($request->token) {
return redirect()->to(url()->current().'?'.http_build_query($request->except("token")));
}
return $next($request);
}
}
This will just redirect if there's a token parameter there. If you need to store it somehow you can use session(["token" => $request->token]); to store it before your redirect.
Middleware is the best option. You can attach middleware class, to routes, in web or to single method. My middleware proposal:
namespace App\Http\Middleware;
use Closure;
class ClearFromAttributes
{
/**
* Remove some attributes which makes some confusion.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($request->get('unwanted_param')) {
return $this->removeFromQueryAndRedirect($request, 'unwanted_param');
}
if ($request->has('second_unwanted')) {
return $this->removeFromQueryAndRedirect($request, 'second_unwanted');
}
return $next($request);
}
/**
* Remove and make redirection.
*
* #param \Illuminate\Http\Request $request
* #param string $parameter
* #return mixed
*/
public function removeFromQueryAndRedirect($request, string $parameter)
{
$request->query->remove($parameter);
return redirect()->to($request->fullUrlWithQuery([]));
}
}
Of course, I have more complicated conditions in the handle method, in reality.
Usage in controller constructor without touching Kernel file:
$this->middleware(ClearFromAttributes::class)->only('index');
This is a nice option, for single usage.
Laravel 7
You can remove parameter(s) from url by passing null to fullUrlWithQuery function like below:
request()->fullUrlWithQuery(['token ' => null])
Laravel 8 added fullUrlWithoutQuery($keys)
class RemoveParameterFromRequest
{
public function handle(Request $request, Closure $next)
{
if ($request->has('unwanted_parameter')) {
return redirect()->to($request->fullUrlWithoutQuery('unwanted_parameter'));
}
return $next($request);
}
}

laravel auth middleware not redirectly on intended page

I am using hesto/multi-auth package
as default if i have assigned the auth middleware to a route the so after login it should redirect me back to the intended page but it's doing only the first time..
everything working exactly i want only the first time but once i logout and try to access the route again it does go to login page and than redirects to the user/home, but first time it works perfect see the 40 sec video
http://neelnetworks.org/video/laravel.mp4
any solution for this?
these are my web routes
Route::get('/', 'PagesController#getIndex')->middleware('user');
Route::group(['prefix' => 'user'], function () {
Route::get('/login', 'UserAuth\LoginController#showLoginForm');
Route::post('/login', 'UserAuth\LoginController#login');
Route::post('/logout', 'UserAuth\LoginController#logout');
Route::get('/register', 'UserAuth\RegisterController#showRegistrationForm');
Route::post('/register', 'UserAuth\RegisterController#register');
Route::post('/password/email', 'UserAuth\ForgotPasswordController#sendResetLinkEmail');
Route::post('/password/reset', 'UserAuth\ResetPasswordController#reset');
Route::get('/password/reset', 'UserAuth\ForgotPasswordController#showLinkRequestForm');
Route::get('/password/reset/{token}', 'UserAuth\ResetPasswordController#showResetForm');
});
here is my Pages Controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PagesController extends Controller
{
public function getIndex()
{
return "hello";
}
}
first time it works perfectly why not after we logged in once?
it works again if i clear all my cache and cookies, is this a default behaviour or is this a bug in laravel? can you please clarify or is it a issue with the package
the issue has been raised in github https://github.com/Hesto/multi-auth/issues/46
Make your showLoginForm method like this inside your UserAuth/LoginController.php
public function showLoginForm()
{
session()->put('url.intended',url()->previous());
return view('user.auth.login');
}
Because it changes the previous url when posting form to /user/login and you will be redirected to /user/home if you logged in
after so much of digging i found out the correct solution
in RedirectIfNot{guard-name} eg RedirectIfNotAdmin
we need to add this line
session()->put('url.intended', url()->current());
so the middleware will look like this
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfNotAdmin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $guard = 'admin')
{
if (!Auth::guard($guard)->check()) {
session()->put('url.intended', url()->current());
return redirect('/admin/login');
}
return $next($request);
}
}
Default redirect for laravel after login is to go to /home set in the LoginController:
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/home';
and there is default middleware RedirectIfAuthenticated
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/home');
}
return $next($request);
}
}
and in app/Http/Controllers/Auth/RegisterController.php
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after login / registration.
*
* #var string
*/
protected $redirectTo = '/home';
So that is where you need to make changes in order to work your way...

New registered user to be redirected to the password reset screen

I'm quite new to Laravel and have been stumped on a problem for 2 days - I'd be grateful for some guidance.
I'm using the default out-of-the-box User authentication system with Laravel 5.3. A new user is created automatically behind the scenes by an existing Admin user - I will in time hide the user registration page. I have also successfully set up middleware to check if a user is newly registered (by looking for a null 'last_logged_in_date' that I've added to the migration).
All I want to happen is for a new registered user to be redirected to the password reset screen that ships with Laravel (again, in time I will create a dedicated page). I would like this to happen within the middleware file. So far, my middleware looks like this:
<?php
namespace App\Http\Middleware;
use Closure;
use App\Http\Controllers\Auth;
class CheckIfNewUser
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = $request->user();
if (! is_null($user->last_logged_in_date )) {
return $next($request);
}
// This is where I'm stuck!!!
}
}
I'm not sure what code to enter at the location indicated by the comments above. I've tried sendResetLinkEmail($request); etc and have imported what I though were the correct classes but I always end up with a Call to undefined function App\Http\Middleware\sendResetLinkEmail() message irregardless of what I 'use' at the top of my class.
Where am I going wrong? Thanks!
Well that happens because you have not defined your sendResetLinkEmail($request) function yet. You can do it like this, or you can create a new class with that and then call the class.
Call the trait SendsPasswordResetEmails and then access it with $this since traits are not classes and you cannot access their members directly.
<?php
namespace App\Http\Middleware;
use Closure;
use App\Http\Controllers\Auth;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
class CheckIfNewUser
{
use SendsPasswordResetEmails;
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = $request->user();
if (! is_null($user->last_logged_in_date )) {
return $next($request);
}
// This is where I'm stuck!!!
//EDIT
//return $this->SendsPasswordResetEmails->sendResetLinkEmail($request);
return $this->sendResetLinkEmail($request);
}
}

Resources