How to make 3 level authentication system in laravel? - php

I have an existing project build with Laravel 5.5. It has a USER login and Admin login. Now I want to add a 3rd authentication AUTHOR login. I have copy pasted admin files in author folder and edited them replacing admin by author . But it's not working even I added author in handle.php and config/auth.
I don't want to use roles.
Here are my codes:
Handler.php
protected function unauthenticated($request, AuthenticationException $exception) {
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
$guard = array_get($exception->guards(),0);
switch ($guard) {
case 'admin':
return redirect()->guest(route('admin.login'));
break;
default:
return redirect()->guest(route('login'));
break;
}
}
protected function unauthenticated($request, AuthenticationException $exception) {
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
$guard = array_get($exception->guards(),0);
switch ($guard) {
case 'author':
return redirect()->guest(route('author.login'));
break;
default:
return redirect()->guest(route('login'));
break;
}
}
Redirectif authenticated
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) {
switch ($guard) {
case 'admin':
if (Auth::guard($guard)->check()) {
return redirect('/admin-dashboard');
}
break;
default:
if (Auth::guard($guard)->check()) {
return redirect('/user/dashboard');
}
break;
}
return $next($request);
}

Related

Laravel 8 | Redirect according to role after login

i am using Laravel as Framework, I'm creating a page with various types of roles, I have the authentication controlled with a middleware, so far so good. My problem is with the redirection after login. I have my users table with a field called "Rol" I need, before entering the system, to verify that "Rol" has my user and according to that, I am redirected to a dashboard or another.
Route::get('/dashboard', [GeneralController::class,'redirectAfterLogin'])->middleware(['auth'])->name('dashboard');
i am using this in the routes. i have un general controller with a function called "redirectAfterLogin"
This is my function
public function redirectAfterLogin(Request $request){
$role = $request->user()->role;
switch ($role) {
case 'Admin':
return redirect(route('admin/dashboard'));
break;
case 'SubAdmin':
return redirect(route('cita/addAppointment'));
break;
case 'Medico':
return redirect(route('cita/pattientsToday'));
break;
case 'Paciente':
return redirect(route('cita/decideLevel'));
break;
default:
# code...
break;
}
}
This works for me, but I don't think it's the right way. I know that with a middleware you can control this, but I don't know how, or what else should change for that middleware to work
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure(\Illuminate\Http\Request):
(\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* #param string|null ...$guards
* #return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
if($request->user()->role == "Admin"){
return "/AdminDashboard";
}else{
return "/GeneralDashboard";
}
}
}
return $next($request);
}
}
This middleware is supposed to handle redirects but no matter how I do it it doesn't happen
Ok, I managed to find the solution. I implemented a predesigned login with Brezze (I think that's how it is written) The point is that to redirect it creates a controller called "AuthenticatedSessionController"
This has the "store" method where the verification of the session data is done and if they are correct it is redirected to "HOME"
This is where we put our logic, in my case I did it with a switch.
class AuthenticatedSessionController extends Controller
{
/**
* Handle an incoming authentication request.
*
* #param \App\Http\Requests\Auth\LoginRequest $request
* #return \Illuminate\Http\RedirectResponse
*/
public function store(LoginRequest $request)
{
$request->authenticate();
$request->session()->regenerate();
$role = $request->user()->role;
switch ($role) {
case 'Admin':
return redirect(route('admin/dashboard'));
break;
case 'SubAdmin':
return redirect(route('cita/addAppointment'));
break;
case 'Medico':
return redirect(route('cita/pattientsToday'));
break;
case 'Paciente':
return redirect(route('cita/decideLevel'));
break;
}
}
Now, there is also a middleware called "RedirectIfAuthenticated", it takes care of the redirects after you are logged in and change the url to the root.
Let me explain, suppose I have 2 users Admin and Public, each one has a different HOME, when logging in who redirects you to the correct HOME, it is the "AuthenticatedSessionController" controller, and if after logging in you write in the URL
"http://My_domain/" (i mean, the root) will be the middleware "RedirectIfAuthenticated" who makes the redirection to the correct HOME. The controller only works when you login, the other times the middleware will do it.
In my middleware i have this.
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure(\Illuminate\Http\Request):
(\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* #param string|null ...$guards
* #return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
$role = $request->user()->role;
switch ($role) {
case 'Admin':
return redirect(route('admin/dashboard'));
break;
case 'SubAdmin':
return redirect(route('cita/addAppointment'));
break;
case 'Medico':
return redirect(route('cita/pattientsToday'));
break;
case 'Paciente':
return redirect(route('cita/decideLevel'));
break;
}
}
}
return $next($request);
}
Both the controller and the middleware are created by Brezze, I don't know how it will work with other login templates. But at least in Brezze I think this would be the correct way to redirect.
Your problem is return string, you need add return redirect(url_name)
Try this code, I think she will help you.
public function handle(Request $request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
switch (Auth::guard($guard)->user()->role){
// Redirect Admin Dashboard
case 'Admin':
return redirect('/AdminDashboard');
break;
// If need any Roles for example:
case: 'RoleName':
return redirect('url');
break;
default: return redirect('/GeneralDashboard');
}
}
}
return $next($request);
}

How to create a custom error page with variables in laravel 8

Good morning everyone, how to create a custom error page with variables in laravel 8 ? So, I want to display an error page with #extend('layouts.app') where in this layouts.app I give a variable such as $general to display the data in the generals table.
I've tried with the code below, but the result is still Undefined variable: general.
Exceptions\Handler.php
<?php
namespace App\Exceptions;
use App\Models\General;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
use Exception;
use Illuminate\Support\Arr;
use Illuminate\Auth\AuthenticationException;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* #var array
*/
protected $dontReport = [
//
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* #var array
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*
* #return void
*/
public function register()
{
$this->reportable(function (Throwable $e) {
//
});
}
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
$guard = Arr::get($exception->guards(), 0);
$route = 'login';
if ($guard == 'admin') {
$route = 'admin.login';
}
return redirect()->route($route);
}
public function render($request, Throwable $exception)
{
if($this->isHttpException($exception)){
switch ($exception->getCode()) {
case 404:
//return redirect()->route('404');
$general = General::find(1);
return response()->view('errors.404', ['general' => $general], $exception->getCode());
break;
case 405:
return response()->view('errors.405', [], $exception->getCode());
break;
case 500:
return response()->view('errors.500', [], $exception->getCode());
break;
}
}
return parent::render($request, $exception);
}
}
errors\404.blade.php
#extends('layouts.front')
#section('title', __('Not Found'))
#section('code', '404')
#section('message', __('Not Found'))
what is the correct way to add variables in laravel 8 error page? thanks :)
You can create your own service provider (or just use App\Providers\AppServiceProvider)
In boot method register View::composer, which will listen on error-page views
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
// Using closure based composers...
View::composer('errors::404', function ($view) {
$general = General::find(1);
$view->with('general', $general);
});
}
you can also use wildcard 'errors::*'

Laravel - Redirect authenticated users

In my Laravel application I have a registration system that uses the default scaffolding created via php artisan make:auth to register new users, but after logging in I wanted to take the user to another page called member-type so that they can select what type of member they'd like to be.
I utilitized protected function authenticated(Request $request, $user) which comes from AuthenticatesUsers to check that a user has successfully logged in, I then check whether a member type is set.
The method looks like this:
/**
* The user has been authenticated.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function authenticated(Request $request, $user)
{
Log::info("{$user->log_reference} logged in to their account with IP: {$request->getClientIp()}");
if(!$user->investor_type_selected){
// dd('I NOT SELECTED');
return redirect()->route('user.investor-type');
} elseif(!$user->member_type_selected){
dd('M NOT SELECTED');
return redirect()->route('user.member-type');
} else{
dd('BOTH SELECTED');
return redirect()->route('user.dashboard');
}
}
The methods member_type_selected andinvestor_type_selectedcome from myUser` model and they look like this:
/**
* Check whether this user has selected an investor type
*/
public function getInvestorTypeSelectedAttribute()
{
return !empty($this->investor_type) ? true : false;
}
/**
* Check whether this user has selected an investor type
*/
public function getMemberTypeSelectedAttribute()
{
return !empty($this->member_type) ? true : false;
}
Pretty simple stuff.
The dump and die was there to test whether the statements were executing.
Anyway, the issue I have is with the Middleware RedirectIfAuthenticated which looks like this as I'm using a custom guard:
/**
* 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)
{
switch ($guard) {
case 'admin':
if (Auth::guard($guard)->check()) {
return redirect()->route('admin.dashboard');
}
break;
default:
if (Auth::guard($guard)->check()) {
return redirect()->route('user.dashboard');
}
break;
}
return $next($request);
}
Now, as soon as a user is authenticated this kicks in and bypasses my redirects with authenticated. I need this Middleware generally to make sure users get back to their dashboard, but is there a way to prevent this bypassing my redirects?
no need to override authenticated function , try this in your RedirectIfAuthenticated middleware
public function handle($request, Closure $next, $guard = null)
{
switch ($guard) {
case 'admin':
if (Auth::guard($guard)->check()) {
return redirect()->route('admin.dashboard');
}
break;
default:
if (Auth::guard($guard)->check()) {
$user = Auth::guard($guard)->user();
if(!$user->investor_type_selected){
return redirect()->route('user.investor-type');
} elseif(!$user->member_type_selected){
return redirect()->route('user.member-type');
} else{
return redirect()->route('user.dashboard');
}
}
break;
}
return $next($request);
}

I want to redirect users when they after login, to profile page

I want to redirect user to profile page when they log in. But, it directs the to home ('/') page. Sometimes, it works if I open it in incognito mode. but not every time.
Following is my Login controller
class LoginController extends Controller
{
use AuthenticatesUsers;
protected function redirectTo()
{
return '/profile';
}
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct(Request $request)
{
if($email = $request->user) {
$user = User::where('email', $email)->first();
if($user && $user->auto_login_key == $request->key) {
Auth::loginUsingId($user->id);
} else {
Redirect::to('/login')->send();
}
}
$this->middleware('guest')->except('logout');
}
}
And this is my Redirected authenticated miidleware
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('/profile');
}
return $next($request);
}
}
You can use return redirect('/profile'); inside your authentication function, for exmaple:
public function __construct(Request $request)
{
if($email = $request->user) {
$user = User::where('email', $email)->first();
if($user && $user->auto_login_key == $request->key) {
Auth::loginUsingId($user->id);
return redirect('/profile');
} else {
Redirect::to('/login')->send();
}
}
$this->middleware('guest')->except('logout');
}
Don't change anything, anywhere. In your LoginController, just change your $redirectTo variable to '/profile':
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/profile';
As it is working in incognito, the issue is just with cache. You can hard-reload (reload and clear cache) by pressing Ctrl + F5
AS i understand your problem, you have to first clear cache after that type of changes and make sure your browser cache is clear.
return redirect('/profile');

Error in Handler Class - Laravel

I am using Laravel 5.5 and trying to implement multi authentication for users and admin. I am getting this error when i try to call admin login form in browser.
Error :
Declaration of App\Exceptions\Handler::unauthenticated($request, App\Exceptions\AuthenticationException $exception) should be compatible with Illuminate\Foundation\Exceptions\Handler::unauthenticated($request, Illuminate\Auth\AuthenticationException $exception)
Here is my unauthenticated function in app/Exceptions/Handler:
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
$guard = array_get($exception->guards(), 0);
switch ($guard) {
case 'admin':
$login = 'admin.login';
break;
default:
$login = 'login';
break;
}
return redirect()->guest(route($login));
}
Please help me to resolve this issue.
You forgot to add use Illuminate\Auth\AuthenticationException at the top of your file
I am using Laravel 7.X
And I prefer to do that in Authenticate middleware
I did it like bellow and It is working well for me.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Support\Arr;
class Authenticate extends Middleware
{
protected $guards = [];
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string[] ...$guards
* #return mixed
*
* #throws \Illuminate\Auth\AuthenticationException
*/
public function handle($request, Closure $next, ...$guards)
{
$this->guards = $guards;
return parent::handle($request, $next, ...$guards);
}
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* #param \Illuminate\Http\Request $request
* #return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
if (Arr::first($this->guards) === 'admin') {
return route('admin.login');
}
return route('trainee.login');
}
}
}
Thank you for your recent answer Thanh Nguyen. My custom auth middleware is work with the latest version
if (Arr::first($this->guards) === 'admin') {
return route('admin.login');
}
return route('customer.login');
Previously using unauthenticated function inside Handler.php to replace the parent function.
protected function unauthenticated($request, AuthenticationException $exception)
{
$guard = Arr::get($exception->guards(), 0);
switch ($guard) {
case 'respondent':
$login = 'respondents.login';
break;
case 'admin':
$login = 'admin.login';
break;
default:
$login = 'admin.login';
break;
}
return $request->expectsJson()
? response()->json(['message' => $exception->getMessage()], 401)
: redirect()->guest(route($login));
}
Both is working, but there was likely an issue for latest version on array_get to obtain guards we use:
$guard = array_get($exception->guards(), 0);
For anyone facing this issue, this method has been deprecated for Laravel 7.* and above
Error in Handler Class - Laravel
public function handle($request, Closure $next)
With
public function handle($request, Closure $next, ...$auth)

Categories