I have no idea why I keep getting this lately by just simply navigate between pages.
Call to a member function setCookie() on null
This is what I have in my AdminMiddleware
<?php
namespace App\Http\Middleware;
use App\Article;
use Closure, View, Auth ;
use Illuminate\Contracts\Auth\Guard;
class AdminMiddleware
{
/**
* 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)
{
if ( Auth::user()->type !== "Admin") {
return View::make('layouts.share.errors.404');
}
return $next($request);
}
}
I'm on Laravel 5.8.
The error occurs when you are logged in as a non Admin because you are returning a View in your AdminMiddleware instead of a Response.
Replace:
if ( Auth::user()->type !== "Admin") {
return View::make('layouts.share.errors.404');
}
With:
if ( Auth::user()->type !== "Admin") {
return response()->view('layouts.share.errors.404', [], 404);
}
To expand on #Chin Leung's answer and to properly return a 404 not found status code
if ( Auth::user()->type !== "Admin") {
return response()->view('layouts.share.errors.404', [], 404);
}
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'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 am specifically trying to get Sanctum's Guard class to look for the API token in a JSON request body if it can't find it in the Authorization header. I simply need to add an elseif after it checks for the bearer token.
So question is: What is the best way to override this method (or class) with my own, without touching the original Sanctum files?
<?php
namespace Laravel\Sanctum;
use Illuminate\Contracts\Auth\Factory as AuthFactory;
use Illuminate\Http\Request;
class Guard
{
/**
* The authentication factory implementation.
*
* #var \Illuminate\Contracts\Auth\Factory
*/
protected $auth;
/**
* The number of minutes tokens should be allowed to remain valid.
*
* #var int
*/
protected $expiration;
/**
* Create a new guard instance.
*
* #param \Illuminate\Contracts\Auth\Factory $auth
* #param int $expiration
* #return void
*/
public function __construct(AuthFactory $auth, $expiration = null)
{
$this->auth = $auth;
$this->expiration = $expiration;
}
/**
* Retrieve the authenticated user for the incoming request.
*
* #param \Illuminate\Http\Request $request
* #return mixed
*/
public function __invoke(Request $request)
{
if ($user = $this->auth->guard('web')->user()) {
return $this->supportsTokens($user)
? $user->withAccessToken(new TransientToken)
: $user;
}
if ($token = $request->bearerToken()) {
$model = Sanctum::$personalAccessTokenModel;
$accessToken = $model::where('token', hash('sha256', $token))->first();
if (! $accessToken ||
($this->expiration &&
$accessToken->created_at->lte(now()->subMinutes($this->expiration)))) {
return;
}
return $this->supportsTokens($accessToken->tokenable) ? $accessToken->tokenable->withAccessToken(
tap($accessToken->forceFill(['last_used_at' => now()]))->save()
) : null;
}
}
/**
* Determine if the tokenable model supports API tokens.
*
* #param mixed $tokenable
* #return bool
*/
protected function supportsTokens($tokenable = null)
{
return in_array(HasApiTokens::class, class_uses_recursive(
$tokenable ? get_class($tokenable) : null
));
}
}
I don't know if you've already figured out but I think you need to add an entry in your AppServiceProvider boot method and override configureGuard functionality placed in SanctumServiceProvider at line 94.
app/Providers/AppServiceProvider.php
Auth::resolved(function ($auth) {
$auth->extend('sanctum', function ($app, $name, array $config) use ($auth) {
return tap($this->createGuard($auth, $config), function ($guard) {
$this->app->refresh('request', $guard, 'setRequest');
});
});
});
You will also need to override createGuard function to specify your custom Guard class with the functionality you require.
In my web.php I have a route
Route::get('summary_average_fee', 'Summary#AverageFee')->middleware('CheckParams#dateLimits');
Im trying to refrence the dateLimits function in the CheckParams class
My CheckParams class, saved as CheckParams.php in the Middleware folder
<?php
namespace App\Http\Middleware;
use Closure;
class CheckParams
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function dateLimits($request, Closure $next)
{
isEmpty($request->input('startDate'), 'NO_START_DATE');
isEmpty($request->input('endDate'), 'NO_END_DATE');
return $next($request);
}
private function isEmpty($value, $error, $status)
{
if(empty($value))
{
return response()->json($error, 422);
}
}
}
In the kernal.php file I add this to the routeMiddleware array
'CheckParams' => \App\Http\Middleware\CheckParams::class
When it runs, I get the error that Class CheckParams#dateLimits does not exist
Seems to me that your middleware should be rewritten and update the usage:
use App\Http\Middleware\CheckParams;
Route::get('summary_average_fee', 'Summary#AverageFee')->middleware(CheckParams::class);
Middleware:
namespace App\Http\Middleware;
use Closure;
class CheckParams
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$this->isEmpty($request->input('startDate'), 'NO_START_DATE');
$this->isEmpty($request->input('endDate'), 'NO_END_DATE');
return $next($request);
}
private function isEmpty($value, $error, $status)
{
if(empty($value))
{
return response()->json($error, 422);
}
}
}
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);
}
}