=========================================================
Edit: Found a better solution:
In Laravel we don't have something like use this one OR use this other middleware, so we had to create a new middleware (in this example my_new_middleware.php). But I dont know any way to implement two existing middlewares in one file and combine them... so we had to rewrite the functionalitties the easiest way - which is auth()->check() OR Auth::check() - this let us check if the user is authenticated (as a specific guard). So we check if the user is authenticated over Sanctum-API by using:
if ( auth("sanctum")->check() ) { ... }
Then we could set the default guard by using:
auth()->shouldUse('guardname');
After that, it should looks like this:
my_new_middlware.php
public function handle(Request $request, Closure $next)
{
if ( auth('sanctum')->check())
{
auth()->shouldUse('sanctum'); //api sanctum auth
return $next($request);
}
else if(auth()->check())
{
auth()->shouldUse('web'); //normal user auth
return $next($request);
}
return response()->json(['error' => 'An error occured.']);
}
Now we can set the middleware to any route. And this routes then should accessible aswell for normal Email/Password users* aswell as Sancum API users.
Notice
By default every routes in api.php are protected by the auth:api middleware, and web.php is protected by auth:web (or just normal auth) middleware.
To make a route in api.php accessible for Email/Password web users we had to set the api guard in the Boot()-function RouteServiceProvider.php as follows:
public function boot()
{
$this->configureRateLimiting();
$this->routes(function () {
Route::prefix('api')
->middleware("web") //change this one from "api" to "web"
->namespace($this->namespace)
->group(base_path('routes/api.php'));
Route::middleware("web")
->namespace($this->namespace)
->group(base_path('routes/web.php'));
});
}
( look: ->middleware("web") //change this one from "api" to "web")
Now all POST routes in api.php are CSRF protected, to remove this protection, we need to add the url-path to VerfifyCsrfToken.php like this:
protected $except = [
'/api/*'
];
to remove all /api/... routes from CSRF protection.
This is how my api.php looks like at the end:
//this routes are accessible for normal users aswell as api users
Route::middleware(["my_new_middleware"])->group(function () {
Route::prefix('/both')->group(function () {
Route::get('/some', [accessController::class, 'someData']);
Route::post('/other', [accessController::class, 'someCreate']);
});
});
//this routes are accessible only for api users (to keep the original functionallity of api.php)
Route::middleware(["auth:api", "auth:sanctum"])->group(function () {
Route::prefix('/onlyapi')->group(function () {
Route::get('/xy', [accessController::class, 'apiData']);
Route::post('/abc', [accessController::class, 'apiCreate']);
});
});
I hope that helps the few people who will visit this site in the next few years after googeling for houres :D
===========================================================
Really bad and Experimental Solution (use the other solution recommended)
Created a new Middleware, which is checking if user is logged in over normal login or with Sanctum API Token:
//my middleware
public function handle(Request $request, Closure $next)
{
if ( auth('sanctum')->check())
{
$request['__current_guard'] = 'sanctum';
return $next($request);
}
else if(auth()->check())
{
$request['__current_guard'] = '';
return $next($request);
}
return response()->json(['error' => 'User Authentication isnt defined.']);
}
Then I store into this middleware a new key into the $request which you do like this:
//first way
$request['mykey'] = 'myvalue';
// second way
Request()->request->add(['mykey' => 'myvalue']);
In the controller know I can access Request('__curent_guard'); , which should be 'sanctum' if logging in via Token, and an empty string when we logged in the default way.
//my controller
public function getUserName(): string
{
$user_name = auth( Request('__current_guard') )->user()->name;
return $user_name;
}
But notice that this is a really Experimental and defenitly not Recommended way of doing this.