TL;DR
In your App\Http\Middleware\Authenticate middleware, add the following to override the parent handle method. This will remove the api_token from the request and cause authentication to fail if the user passes the token in the request payload or as query string fail. It should still work if passed as a Bearer token which what I assume you are trying to achieve.
/**
* 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)
{
$request->request->set('api_token', null);
return parent::handle($request, $next, ...$guards);
}
The long story....
In config/auth.php you should have the below config:
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
So when you use auth:api, it matches the api argument to the key of the array above to get the name of the driver to use for authentication, in this instance token.
So when using the Illuminate\Auth\Middleware\Authenticate, the handle method passes an array of guards to check, in this case, the value would be ['api'].
It then checks the config file to find an entry with that key and locates the config above.
Because the driver name is token, Illuminate\Auth\AuthManager then makes a TokenGuard to handle the authentication of the user.
Line 143:
/**
* Create a token based authentication guard.
*
* @param string $name
* @param array $config
* @return \Illuminate\Auth\TokenGuard
*/
public function createTokenDriver($name, $config)
{
// The token guard implements a basic API token based guard implementation
// that takes an API token field from the request and matches it to the
// user in the database or another persistence layer where users are.
$guard = new TokenGuard(
$this->createUserProvider($config['provider'] ?? null),
$this->app['request']
);
$this->app->refresh('request', $guard, 'setRequest');
return $guard;
}
The Illuminate\Auth\TokenGuard then uses the getTokenForRequest method to extract the token from the request:
Line 78:
/**
* Get the token for the current request.
*
* @return string
*/
public function getTokenForRequest()
{
$token = $this->request->query($this->inputKey);
if (empty($token)) {
$token = $this->request->input($this->inputKey);
}
if (empty($token)) {
$token = $this->request->bearerToken();
}
if (empty($token)) {
$token = $this->request->getPassword();
}
return $token;
}
So setting the api_token value to null on the request would ensure it fails for the first 2 checks and should still allow it to pass if a valid Bearer token is presented.