How to validate routes if a user is admin or not? - laravel

//This is the middle ware
public function handle($request, Closure $next)
{
if(auth()->user()->isAdmin()) //isAdmin is a function in the User model which checks if the user is admin or not
{
return redirect('/admin');
} else {
return redirect('/home');
}
return $next($request);
}
//I already registered this middleware in kernel as well as verifyUser
Route::middleware(['auth', 'verifyUser'])->group(function() {
Route::get('/home', 'HomeController#index')->name('home');
Route::get('/admin', 'AdminController#index')->name('admin');
Route::get('/users/profile', 'UserController#view')->name('users.view-profile');
Route::get('/users/edit_profile', 'UserController#edit')->name('users.edit-profile');
});
Th main problem here is it shows this error in the browser
The page isn’t redirecting properly
Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
This problem can sometimes be caused by disabling or refusing to accept cookies.

You're telling Laravel to redirect admins to /admin, and non-admins to /home.
However, you've made /admin and /home subject to that middleware, too, so when the user gets to /home it redirect them to /home again (and again, and again, and again, forever).
You likely need two changes:
A new middleware, applied only to admin routes, that only redirects non-admins away from those routes.
Put your home/admin logic as a one-off post-login step instead of on every pageview. See the path customization section of the Authentication docs.

Related

Laravel multiple authentication from two different route and view

I want to implement a system where 6 types of users exist. So one is 'customer' who will login by a route like /login and rest of 5 users are admins and only they will be login using another route /system/base-admin. However, 'customer' never login with the /system/base-admin route if anyhow can known this route. And both route have different login form and if they failed to login 'customer' will be redirected /login and admins /system/base-admin.
I know about $guard and middleware check.
Question: How can i implement above scenario and how react professionals with this scenario?
Route::get('/login','CustomerLoginController#processLogin')->name('customer.login');
Route::get('/system/base-admin', 'AdminLoginController#processAdminLogin')->name('system.admin')
My Controller Looks like
public function processLogin(){ return view('customer.login');}
public function processAdminLogin(){ return view('admin.login')}
Thank you in advance.
The only reason I see to have different endpoints for login is to have different views.
Copy your Auth\LoginController, change $redirectTo to redirect to your admin panel. Overwrite AuthenticatesUsers\showLoginForm to show your admin form and update middleware in __construct.
Protect all your admin routes with admin middleware.
Now. Your users CAN login to your panel. BUT nothing will happen since they don't have access.
If you want to show them some kind of message when they try you can overwrite AuthenticatesUsers\login method with something like this
...
if ($this->attemptLogin($request)) {
if(!auth()->user()->isAdmin()){
throw ValidationException::withMessages([
$this->username() => 'You don\'t have access to this page',
]);
}
return $this->sendLoginResponse($request);
}
...

Laravel stuck on email/verify

I just applied the laravel email-verification and wanted to make sure my users are verified, before entering page behind the login.
I added the follwing code:
class User extends Authenticatable implements MustVerifyEmail
...
Auth::routes(['verify' => true]);
...
Route::get('management', function () {
// Only verified users may enter...
})->middleware('verified');
If a user registers he gets a note and an email to verify his mail. He clicks the button in the mail, gets verified and everything works perfectly well.
But I discovered another case:
If the user registers and won't verify his mail, he will always get redirected to email/verify.
For example if accidentally having entered a wrong email, he can't even visit the register page, because even on mypage.com/register he gets redirected to mypage.com/email/verify!
Is this done on purpose by Laravel? Did I miss something? Do I have to / is it possible to exclude the login/register pages from verification?
Thank you in advance
I have this issue before, I have this way to resolve that, if you want to customize it you can consider this way.
In LoginController.php you can add this a little bit code, I overwriting the default login method:
public function login(Request $request)
{
$this->validateLogin($request);
$user = User::where($this->username(), $request->{$this->username()})->first();
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if (method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($user->hasVerifiedEmail()) {
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
})
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
You can overwrite and add a new parameter to the sendFailedLoginResponse too to let the method know when to redirect to email/verify page or just add else in $user->hasVerifiedEmail() if block to redirect him to email/verify page
EDIT:
You can delete $this->middleware('guest') in LoginController and RegisterController to make logged in user can go to register and login page, but it will be weird if someone who already logged in can login or register again.
I had the same problem and I solved it very user friendly... (I think!)
First: Inside View/Auth/verify.blade.php put a link to the new route that will clear the cookie:
My mail was wrong, I want to try another one
Second: On your routes/web.php file add a route that will clear the session cookie:
// Clear session exception
Route::get('/clear-session', function(){
Cookie::queue(Cookie::forget(strtolower(config('app.name')) . '_session'));
return redirect('/');
});
This will clear the cookie if the user press the button, and redirect to home page.
If this doesn't work, just make sure that the cookie name you are trying to forget is correct. (Use your chrome console to inspect: Application -> cookies)
For example:
Cookie::queue(Cookie::forget('myapp_session'));

Laravel Auth::id() return null after login

I have a login form to access to my web page.
In my local computer everything works fine. But now I upload my project to my server and when I login the directive #auth() is null.
I put in my controller this: dd(Auth::id()); and in my local server returns a Id but in the production server returns null...
in web.php I have tis code:
Route::group(['middleware' => 'role:admin' OR 'role:user'], function () {
Route::get('/users/inicio', function(){
dd(Auth::id());
return view('frontend.dashboardUser');});
});
This return null
Can you help me?
Thank you
I think there might be some session problem, It might not be maintaining the session state.
My suggestion:
Try echo session_id() multiple times, If every time different id is generated then there will be some problem with the session on server otherwise not.
Have you registered a new user after you pushed your code to the production? I mean have you logged in using an existing user on production? I believe your production and local Database is different and the user who exists on local does not exist on production DB.
Register a new user and login as the new user and then try accessing the route to see if you get the auth id.
For a security reason, you can't access the login user or any other session into the web.php file as well as a constructor of the class.
To archive this you can use middleware something like this:
public function __construct() {
$this->middleware(function (Request $request, $next) {
if (!\Auth::check()) {
return redirect('/login');
}
$this->userId = \Auth::id(); // you can access user id here
return $next($request);
});
}
This link can help you more. Good luck!!!

Laravel custom redirect if user is not logged in?

I have on my project route groups for 4 subdomains, on one subdomain I set 'middleware' => 'auth', it works, but if guest try to access this protected subdomain he is redirected to sub.project.com/login and not to project.com/login, where can I set it correctly?
You can try to handle the redirect within the middleware
public function handle($request, Closure $next, $guard = null)
{
if ($request->getPort() != 80 || Auth::guard($guard)->guest()) {
//to account for json or ajax requests
if ($request->ajax() || $request->wantsJson())
{
return response('Unauthorized.', 401);
}
return redirect('auth/login')->withErrors(['must login']);
}
return $next($request);
}
By default it shouldn't be a problem. On by default I mean, you had to explicitly tell Laravel where to redirect, if you didn't do so (didn't alter middleware logic in any way), there are 3 things that come in play:
Your .htaccess (or httpd.conf) is messed up.
Certificate issues. Do you have SSL enabled on the login page? If the website config file points to a cert issued for not the same domain, it causes such problems.
config/app.php includes the wrong domain
(It's a stupid question on my part, but could you please confirm that it redirects to and not renders the content available on that subdomain? To exclude some possibilities.)

Laravel 5.2 4 rolle

I need help how to make laravel 5.2 authenticate with 4 rolls?
guest
registered
support
admin
I make something but every time I get
ERR_TOO_MANY_REDIRECTS.
Route::group(['middleware' => ['web','isAdmin']], function () {
Route::get('/', function(){
return view('admin');
});
});
Route::group(['middleware' => ['web','isSupport']], function () {
Route::get('/support', function(){
return view('support');
});
});
Middleware
public function handle($request, Closure $next)
{
if (Auth::user()->role == '3') {
return $next($request);
}
if(Auth::guest()){
redirect('login');
}else
return redirect('/');
}
}
If I assume, you add isAdmin middleware to path /. isAdmin middleware is checking that user have a proper role (role with id === 3). If not, then redirect to /.
So only user with role 3 can access to path / but system still try redirect to this path. Infinite loop.
Yes, #grzegorz has the correct answer already posted on here I believe. But I will try to explain it clearly.
So in your route for the root of your application ('/') you tell Laravel to process middleware to authenticate users. This in and of itself is not unusual. The middleware runs a function to see if a user basically has level 3 authority and if they do then you return the request url (which is also '/' and the process continues in an infinite loop, because they are sent to the '/' url, then it processes and returns the same url again, causing it to process middleware again, going forever. This is why you are getting an error saying that there are too many redirects, because it redirects a whole bunch of times with no end in sight and eventually Laravel stops it for you and returns an error.
How to fix this problem?
Easy, you have a good start already. But what I would do is that when you check to see if a user has auth level 3 and they do, then simply return true. There is no need to return the requesting url, because this is middleware, so its running when someone requests a URL. So the purpose of your middleware would be to return true meaning "don't do anything, just continue". Then if the user does not have authority level 3, then you would want to redirect them away from this page. Do an actual redirect though (as opposed to returning a url string like you are now). So you would want to do something like this:
return redirect()->route('login');
You could also add some flash data to this with an error message to display to the user something telling them that they do not have access to this route.
Last note:
It would be strange to only allow high level authority users to be the only ones that can access a homepage. Maybe this is what you want, but it seems weird so I wanted to mention it in case it is unintended. What I wonder you are doing is maybe trying to display different information on the homepage depending if someone is logged in or not. if this is the case, then you don't want to use middleware, you want to move this to the controller and then conditionally add html for logged in users or something like that.

Resources