I am stuck with getting the redirectTo() function override in my LoginController.php as shown in the Laravel docs here.
My controller contains:
/**
* URI where we redirect to after login
*
* #var string
*/
protected $redirectTo = 'player/home';
/**
* Set route redirect
*
* #return mixed
*/
protected function redirectTo()
{
dd("STOP"); <-- does not trigger
if (session()->has('game.details')) {
return route(session()->get('game.details.setup_route'));
} else {
return 'player/home';
}
}
Why would the dd never trigger and the page always redirects to player/home? Thanks
If you comment
$this->middleware("guest")
in the constructor of Auth\RegisterController or change the line about guest middleware in the Kernel.php it will be worked.
Although I did not get the method override working, I solved it by changing these lines in the login method:
if ($this->attemptLogin($request)) {
session()->put('game.details', Game::findByUUIDOrFail($uuid));
$this->redirectTo = route(session()->get('game.details.setup_route'));
return $this->sendLoginResponse($request);
}
If you have run php artisan auth
change the RedirectIfAuthenticated Middleware like so
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');//change the redirect here
}
return $next($request);
}
}
Related
I'm using Laravel 9 with Breeze and below is all the modifications. What I did was set the session_driver to database instead of file. Right now I am using subdomains for users but later on ill be adding the ability to buy and set a domain for each tenant so that is why im using the subdomainOrDomain middleware instead of just the domain middleware by stancl. My problem is that the auth session wont be set and i dont see any entries in the tenants database within the table sessions. So no session gets set at all. The central domain also has auth and it works perfectly but just not the tenant.
App\Http\Kernel.php
protected $middlewareGroups = [
//...
'tenant' => [
\App\Http\Middleware\InitializeTenancyByDomainOrSubdomain::class,
\Stancl\Tenancy\Middleware\PreventAccessFromCentralDomains::class,
],
'universal' => [],
];
App\Http\Middlware\InitializeTenancyByDomainOrSubdomain
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Str;
use App\Http\Middleware\InitializeTenancyByDomain;
use App\Http\Middleware\InitializeTenancyBySubdomain;
class InitializeTenancyByDomainOrSubdomain
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->isSubdomain($request->getHost()))
{
return app(InitializeTenancyBySubdomain::class)->handle($request, $next);
}
else
{
return app(InitializeTenancyByDomain::class)->handle($request, $next);
}
}
protected function isSubdomain(string $hostname): bool
{
return Str::endsWith($hostname, config('tenancy.central_domains'));
}
}
App\Http\Middlware\InitializeTenancyByDomain
namespace App\Http\Middleware;
use Closure;
use Stancl\Tenancy\Tenancy;
use Stancl\Tenancy\Resolvers\DomainTenantResolver;
use Stancl\Tenancy\Middleware\IdentificationMiddleware;
class InitializeTenancyByDomain extends IdentificationMiddleware
{
/** #var callable|null */
public static $onFail;
/** #var Tenancy */
protected $tenancy;
/** #var DomainTenantResolver */
protected $resolver;
public function __construct(Tenancy $tenancy, DomainTenantResolver $resolver)
{
$this->tenancy = $tenancy;
$this->resolver = $resolver;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(in_array($request->getHost(), config('tenancy.central_domains'), true))
{
return $next($request);
}
return $this->initializeTenancy(
$request, $next, $request->getHost()
);
}
}
App\Http\Middlware\InitializeTenancyBySubdomain
namespace App\Http\Middleware;
use Closure;
use Exception;
use Illuminate\Support\Str;
use Illuminate\Http\Response;
use Stancl\Tenancy\Exceptions\NotASubdomainException;
class InitializeTenancyBySubdomain extends InitializeTenancyByDomain
{
/**
* The index of the subdomain fragment in the hostname
* split by `.`. 0 for first fragment, 1 if you prefix
* your subdomain fragments with `www`.
*
* #var int
*/
public static $subdomainIndex = 0;
/** #var callable|null */
public static $onFail;
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(in_array($request->getHost(), config('tenancy.central_domains'), true))
{
return $next($request);
}
$subdomain = $this->makeSubdomain($request->getHost());
if (is_object($subdomain) && $subdomain instanceof Exception) {
$onFail = static::$onFail ?? function ($e) {
throw $e;
};
return $onFail($subdomain, $request, $next);
}
// If a Response instance was returned, we return it immediately.
if (is_object($subdomain) && $subdomain instanceof Response) {
return $subdomain;
}
return $this->initializeTenancy(
$request,
$next,
$request->getHost()
);
}
/** #return string|Response|Exception|mixed */
protected function makeSubdomain(string $hostname)
{
$parts = explode('.', $hostname);
$isLocalhost = count($parts) === 1;
$isIpAddress = count(array_filter($parts, 'is_numeric')) === count($parts);
// If we're on localhost or an IP address, then we're not visiting a subdomain.
$isACentralDomain = in_array($hostname, config('tenancy.central_domains'), true);
$notADomain = $isLocalhost || $isIpAddress;
$thirdPartyDomain = ! Str::endsWith($hostname, config('tenancy.central_domains'));
if ($isACentralDomain || $notADomain || $thirdPartyDomain) {
return new NotASubdomainException($hostname);
}
return $parts[static::$subdomainIndex];
}
}
Routes\Tenant.php
Route::middleware(['tenant', 'web'])->group(function()
{
Route::get('login', [AuthenticatedSessionController::class, 'create'])
->name('login');
Route::post('login', [AuthenticatedSessionController::class, 'store']);
});
in the tenant routes i have also tried switching the web middleware to guest as is by default with laravel breeze but it trows the $errors not found error (the validation handling variable).
i have two type of api authentication way and i want if my first way fails check santcum laravel auth .
i make midlleware class and but i dont know how to check santcum in that
<?php
namespace App\Http\Middleware;
class UserApiAuthenticated
{
/**
* User authenticator container
* #var UserAuthenticatorServiceInterface
*/
protected UserAuthenticatorServiceInterface $user_authenticator_service;
public function __construct(UserAuthenticatorServiceInterface$user_authenticator_service)
{
$this->user_authenticator_service = $user_authenticator_service;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure(\Illuminate\Http\Request):
(\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* #return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
if ($this->user_authenticator_service->isUserAuthenticated($request)) {
return $next($request);
} elseif () {
}
I would do something like that :
/**
* 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())
{
return $next($request);
}
}
abort(403, 'Unauthenticated')
}
it checks all the guards one by one,
when you use the middleware you set the guards :
->middleware('mymiddleware:web,sanctum')
or with a route group :
Route::group(['middleware' => ['mymiddleware:web,sanctum',
if you have routes in common, you could use both guards at the same time, and for routes that are specific to one authentication method, you can set the correct guard you need
but in the end i would check the auth middleware from laravel, i'm sure it does what you need (Illuminate\Auth\Middleware\Authenticate)
I'm trying to make an e-commerce admin/user authentication I use laravel 8 went register a test account and logged in and this error occured.
Error
Class 'Laravel\Fortify\Actions\Auth' not found
After i logged in a test account it was supposed to result like this
https://ibb.co/Vq5LxBk
C:\Users\ACER\laravel8ecommerce\vendor\laravel\fortify\src\Actions\AttemptToAuthenticate.php:58
This was the line 58
if(Auth::user()->utype === 'ADM')
My code on AttemptToAuthenticate.php
<?php
namespace Laravel\Fortify\Actions;
use Illuminate\Auth\Events\Failed;
use Illuminate\Contracts\Auth\StatefulGuard;
use Illuminate\Validation\ValidationException;
use Laravel\Fortify\Fortify;
use Laravel\Fortify\LoginRateLimiter;
class AttemptToAuthenticate
{
/**
* The guard implementation.
*
* #var \Illuminate\Contracts\Auth\StatefulGuard
*/
protected $guard;
/**
* The login rate limiter instance.
*
* #var \Laravel\Fortify\LoginRateLimiter
*/
protected $limiter;
/**
* Create a new controller instance.
*
* #param \Illuminate\Contracts\Auth\StatefulGuard $guard
* #param \Laravel\Fortify\LoginRateLimiter $limiter
* #return void
*/
public function __construct(StatefulGuard $guard, LoginRateLimiter $limiter)
{
$this->guard = $guard;
$this->limiter = $limiter;
}
/**
* Handle the incoming request.
*
* #param \Illuminate\Http\Request $request
* #param callable $next
* #return mixed
*/
public function handle($request, $next)
{
if (Fortify::$authenticateUsingCallback) {
return $this->handleUsingCustomCallback($request, $next);
}
if ($this->guard->attempt(
$request->only(Fortify::username(), 'password'),
$request->filled('remember'))
) {
if(Auth::user()->utype === 'ADM')
{
session(['utype'=>'ADM']);
return redirect(RouteServiceProvider::HOME);
}
elseif(Auth::user()->utype === 'USR')
{
session(['utype'=>'USR']);
return redirect(RouteServiceProvider::HOME);
}
return $next($request);
}
$this->throwFailedAuthenticationException($request);
}
/**
* Attempt to authenticate using a custom callback.
*
* #param \Illuminate\Http\Request $request
* #param callable $next
* #return mixed
*/
protected function handleUsingCustomCallback($request, $next)
{
$user = call_user_func(Fortify::$authenticateUsingCallback, $request);
if (! $user) {
$this->fireFailedEvent($request);
return $this->throwFailedAuthenticationException($request);
}
$this->guard->login($user, $request->filled('remember'));
return $next($request);
}
/**
* Throw a failed authentication validation exception.
*
* #param \Illuminate\Http\Request $request
* #return void
*
* #throws \Illuminate\Validation\ValidationException
*/
protected function throwFailedAuthenticationException($request)
{
$this->limiter->increment($request);
throw ValidationException::withMessages([
Fortify::username() => [trans('auth.failed')],
]);
}
/**
* Fire the failed authentication attempt event with the given arguments.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
protected function fireFailedEvent($request)
{
event(new Failed(config('fortify.guard'), null, [
Fortify::username() => $request->{Fortify::username()},
'password' => $request->password,
]));
}
My Routes (web php)
<?php
use App\Http\Livewire\CartComponent;
use App\Http\Livewire\CheckoutComponent;
use App\Http\Livewire\HomeComponent;
use App\Http\Livewire\ShopComponent;
use App\Http\Livewire\User\UserDashboardComponent;
use App\Http\Livewire\Admin\AdminDashboardComponent;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
// Route::get('/', function () {
// return view('welcome');
// });
Route::get('/',HomeComponent::class);
Route::get('/shop',ShopComponent::class);
Route::get('/cart',CartComponent::class);
Route::get('/checkout',CheckoutComponent::class);
// Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () {
// return view('dashboard');
// })->name('dashboard');
// For User or Customer
Route::middleware(['auth:sanctum', 'verified'])->group(function(){
Route::get('user/dashboard',UserDashboardComponent::class,)->name('user.dashboard');
});
// For Admin
Route::middleware(['auth:sanctum', 'verified','authadmin'])->group(function(){
Route::get('admin/dashboard',AdminDashboardComponent::class,)->name('admin.dashboard');
});
I would really appreciate a help i'm doing this for my project on school
use Illuminate\Support\Facades\Auth;
use App\Providers\RouteServiceProvider;
from to vendor\laravel\fortify\src\Actions\AttemptToAuthenticate
but you must remove line :
use Laravel\Fortify\Actions\RouteServiceProvider;
Because this line is duplicate for RouteServiceProvider.... but maybe just for my project
use Illuminate\Support\Facades\Auth;
use App\Providers\RouteServiceProvider;
put these two on top of
vendor\laravel\fortify\src\Actions\AttemptToAuthenticate
adding two lines on the top of AttemptToAuthenticate.php file
use Illuminate\Support\Facades\Auth;
use App\Providers\RouteServiceProvider;
For future users;
On AttemptToAuthenticate.php, right under AttemptToAuthenticate.php,
add use Auth;
it will still throw an error class '\laravel\fortify\actions\RouteServiceProvider' not found!
To solve this,
Simply add
use App\Providers\RouteServiceProvider;, to direct it to the default
RouteServiceProvider class.
add
use Illuminate\Support\Facades\Auth;
in class vendor\laravel\fortify\src\Actions\AttemptToAuthenticate
<?php
namespace Laravel\Fortify\Actions;
use Illuminate\Auth\Events\Failed;
use Illuminate\Contracts\Auth\StatefulGuard;
use Illuminate\Validation\ValidationException;
use Laravel\Fortify\Fortify;
use Laravel\Fortify\LoginRateLimiter;
use Illuminate\Support\Facades\Auth;
use App\Providers\RouteServiceProvider;
class AttemptToAuthenticate
{
/**
* The guard implementation.
*
* #var \Illuminate\Contracts\Auth\StatefulGuard
*/
protected $guard;
/**
* The login rate limiter instance.
*
* #var \Laravel\Fortify\LoginRateLimiter
*/
protected $limiter;
/**
* Create a new controller instance.
*
* #param \Illuminate\Contracts\Auth\StatefulGuard $guard
* #param \Laravel\Fortify\LoginRateLimiter $limiter
* #return void
*/
public function __construct(StatefulGuard $guard, LoginRateLimiter $limiter)
{
$this->guard = $guard;
$this->limiter = $limiter;
}
/**
* Handle the incoming request.
*
* #param \Illuminate\Http\Request $request
* #param callable $next
* #return mixed
*/
public function handle($request, $next)
{
if (Fortify::$authenticateUsingCallback) {
return $this->handleUsingCustomCallback($request, $next);
}
if ($this->guard->attempt(
$request->only(Fortify::username(), 'password'),
$request->filled('remember'))
) {
if(Auth::user()->utype === 'ADM')
{
session(['utype'=>'ADM']);
return redirect(RouteServiceProvider::HOME);
}
elseif(Auth::user()->utype === 'USR')
{
session(['utype'=>'USR']);
return redirect(RouteServiceProvider::HOME);
}
return $next($request);
}
$this->throwFailedAuthenticationException($request);
}
/**
* Attempt to authenticate using a custom callback.
*
* #param \Illuminate\Http\Request $request
* #param callable $next
* #return mixed
*/
protected function handleUsingCustomCallback($request, $next)
{
$user = call_user_func(Fortify::$authenticateUsingCallback, $request);
if (! $user) {
$this->fireFailedEvent($request);
return $this->throwFailedAuthenticationException($request);
}
$this->guard->login($user, $request->filled('remember'));
return $next($request);
}
/**
* Throw a failed authentication validation exception.
*
* #param \Illuminate\Http\Request $request
* #return void
*
* #throws \Illuminate\Validation\ValidationException
*/
protected function throwFailedAuthenticationException($request)
{
$this->limiter->increment($request);
throw ValidationException::withMessages([
Fortify::username() => [trans('auth.failed')],
]);
}
/**
* Fire the failed authentication attempt event with the given arguments.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
protected function fireFailedEvent($request)
{
event(new Failed(config('fortify.guard'), null, [
Fortify::username() => $request->{Fortify::username()},
'password' => $request->password,
]));
}
}
use Illuminate\Support\Facades\Auth;
This line should be added at the top of the AttemptAuthenticate.php file.
I had the same error and i solved by adding these lines. use Illuminate\Support\Facades\Auth; use App\Providers\RouteServiceProvider;
Add this to your AttemptToAuthenticate.php file.
use Illuminate\Support\Facades\Auth;
This works fine for me.
I have looked at many similar questions bu they don't approach the real problem. I would like to redirect a user to a certain url just after login depending on a condition about the user.
I know this can be archieved with a middleware so I have tried this in app\Http\Middleware\RedirectIfAuthenticated.php
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::User()->check()) {
$redirect = '/client';
if (Auth::user()->hasRole('admin')){
$redirect = '/admin';
}
return redirect($redirect);
}
return $next($request);
}
}
I realise now this will not work just after login. I'd like to redirect a user depending whether he/she is an admin or a client. I know I could use: protected $redirectPath = '/url/to/redirect'; but I have multiple pages to redirect to.
What is the best way to do this?
You could over-write the redirect method offered up by the trait in app/Http/Controllers/Auth/AuthController.php
public function redirectPath()
{
if (Auth::user()->hasRole('admin')){
return '/admin';
}
return '/client';
}
Put that in your AuthController.php.
I'm having a trouble with creating the "owner" middleware.
For example, I have a Articles and Usermodel associated with user_id key.
I want to add the "owner" middleware to the ArticlesController, so the only owner of that article can edit, update and delete it.
I've been searching for this issue for a while, but never found the code, which would work.
Some of them tried to make it work with Form Requests, but I'm interested in using Middleware.
Create middleware:
php artisan make:middleware OwnerMiddleware
namespace App\Http\Middleware;
use App\Article;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class OwnerMiddleware
{
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$articleId = $request->segments()[1];
$article = Article::findOrFail($articleId);
if ($article->user_id !== $this->auth->getUser()->id) {
abort(403, 'Unauthorized action.');
}
return $next($request);
}
}
Add it to app\Http\Kernel.php:
protected $routeMiddleware = [
'owner' => 'App\Http\Middleware\OwnerMiddleware',
];
Use middleware in your routes:
Route::group(['middleware' => ['owner']], function() {
// your route
});
Alternatively you could use route and middleware parameters, it has some advantages:
Even if the request structure changes your middleware would still work
The middleware is reusable for differents resources
You can use it inside controllers
Here’s the middleware (app/Http/Middleware/AbortIfNotOwner.php):
<?php
namespace App\Http\Middleware;
use Closure;
class AbortIfNotOwner
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string $resourceName
* #return mixed
*/
public function handle($request, Closure $next, $resourceName)
{
$resourceId = $request->route()->parameter($resourceName);
$user_id = \DB::table($resourceName)->find($resourceId)->user_id;
if ($request->user()->id != $user_id) {
abort(403, 'Unauthorized action.');
}
return $next($request);
}
}
Inside app\Http\Kernel.php:
protected $routeMiddleware = [
'owner' => 'App\Http\Middleware\AbortIfNotOwner',
];
Inside your route file (app/Http/routes.php):
Route::group(['middleware' => ['owner:articles']], function() {
// your route
});
And optionally call it in the controller:
public function __construct()
{
$this->middleware('owner:articles', ['only' => ['edit', 'update']]);
}