Skip to content

Commit

Permalink
Improve token guard to not crash when provided with Basic Auth (#2193)
Browse files Browse the repository at this point in the history
  • Loading branch information
ildyria authored Jan 14, 2024
1 parent 4f301c6 commit e1faf33
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 3 deletions.
37 changes: 35 additions & 2 deletions app/Services/Auth/SessionOrTokenGuard.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

/**
* A custom Guard which combines the default Laravel Session Guard with
Expand Down Expand Up @@ -308,8 +310,39 @@ protected function getUserByToken(): ?Authenticatable
{
$token = $this->request->headers->get(self::HTTP_TOKEN_HEADER);

return is_string($token) && $token !== '' ? $this->provider->retrieveByCredentials([
// Skip if token is not found.
if ($token === null || !is_string($token) || $token === '') {
return null;
}

// Skip if token starts with Basic: it is not related to Lychee.
if (Str::startsWith('Basic', $token)) {
return null;
}

// Check if token starts with Bearer
$hasBearer = Str::startsWith('Bearer', $token);
/** @var bool $configLog */
$configLog = config('auth.token_guard.log_warn_no_scheme_bearer');
/** @var bool $configThrow */
$configThrow = config('auth.token_guard.fail_bearer_authenticable_not_found', true);

// If Token does not start with Bearer
if (!$hasBearer && $configLog) {
Log::warning('Auth token found, but Bearer prefix not provided.');
}

// Remove prefix and fetch authenticable.
$token = trim(Str::remove('Bearer', $token));
$authenticable = $this->provider->retrieveByCredentials([
self::TOKEN_COLUMN_NAME => hash(self::TOKEN_HASH_METHOD, $token),
]) ?? throw new BadRequestHeaderException('Invalid token') : null;
]);

return match (true) {
$authenticable !== null => $authenticable,
$hasBearer && $configThrow => throw new BadRequestHeaderException('Invalid token'),
$hasBearer => null,
default => throw new BadRequestHeaderException('Invalid token')
};
}
}
21 changes: 20 additions & 1 deletion config/auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

'guards' => [
'lychee' => [
'driver' => env('ENABLE_TOKEN_AUTH', true) ? 'session-or-token' : 'session', // @phpstan-ignore-line
'driver' => env('ENABLE_BEARER_TOKEN_AUTH', env('ENABLE_TOKEN_AUTH', true)) ? 'session-or-token' : 'session', // @phpstan-ignore-line
'provider' => 'users',
],
],
Expand Down Expand Up @@ -110,4 +110,23 @@
*/

'password_timeout' => 10800,

/*
|--------------------------------------------------------------------------
| Hard fail on bearer token
|--------------------------------------------------------------------------
|
| When a bearer token is found, we fail hard by throwing an exception when the
| associated authenticable (user) is not found.
|
| This is only used if ENABLE_BEARER_TOKEN_AUTH = true
*/

'token_guard' => [
// Hard fail if bearer token is provided but no authenticable user is found
'fail_bearer_authenticable_not_found' => (bool) env('FAIL_NO_AUTHENTICABLE_BEARER_TOKEN', true),

// Log if token is provided but no bearer prefix.
'log_warn_no_scheme_bearer' => (bool) env('LOG_WARN_NO_BEARER_TOKEN', true),
],
];

0 comments on commit e1faf33

Please sign in to comment.