1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2025-12-12 11:14:04 +00:00

Fix cookie identification (#56)

* route cloning: Trim '/' from original route prefixes

* Decrypt cookie if encrypted in request data ID MW

* Fix code style (php-cs-fixer)

* Fix PHPStan error [ci skip]

* Revert "route cloning: Trim '/' from original route prefixes"

This reverts commit 3dc97eba1b3b91b3446bc16fd107385fe835621e.

* Fix code style (php-cs-fixer)

* add a setting for requiring cookie encryption

* Fix code style (php-cs-fixer)

---------

Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
Co-authored-by: Samuel Štancl <samuel@archte.ch>
This commit is contained in:
lukinovec 2024-08-06 02:19:11 +02:00 committed by GitHub
parent 0f7cd2e868
commit 15d12e22c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -5,7 +5,9 @@ declare(strict_types=1);
namespace Stancl\Tenancy\Middleware;
use Closure;
use Illuminate\Cookie\CookieValuePrefix;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;
use Stancl\Tenancy\Concerns\UsableWithEarlyIdentification;
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedByRequestDataException;
use Stancl\Tenancy\Overrides\TenancyUrlGenerator;
@ -21,6 +23,8 @@ class InitializeTenancyByRequestData extends IdentificationMiddleware
public static string $queryParameter = 'tenant';
public static ?Closure $onFail = null;
public static bool $requireCookieEncryption = false;
public function __construct(
protected Tenancy $tenancy,
protected RequestDataTenantResolver $resolver,
@ -38,7 +42,11 @@ class InitializeTenancyByRequestData extends IdentificationMiddleware
TenancyUrlGenerator::$prefixRouteNames = false;
if ($request->method() !== 'OPTIONS') {
return $this->initializeTenancy($request, $next, $this->getPayload($request));
return $this->initializeTenancy(
$request,
$next,
$this->getPayload($request)
);
}
return $next($request);
@ -48,10 +56,17 @@ class InitializeTenancyByRequestData extends IdentificationMiddleware
{
if (static::$header && $request->hasHeader(static::$header)) {
$payload = $request->header(static::$header);
} elseif (static::$queryParameter && $request->has(static::$queryParameter)) {
} elseif (
static::$queryParameter &&
$request->has(static::$queryParameter)
) {
$payload = $request->get(static::$queryParameter);
} elseif (static::$cookie && $request->hasCookie(static::$cookie)) {
$payload = $request->cookie(static::$cookie);
if ($payload) {
$payload = $this->getTenantFromCookie($payload);
}
} else {
$payload = null;
}
@ -70,4 +85,36 @@ class InitializeTenancyByRequestData extends IdentificationMiddleware
{
return (bool) $this->getPayload($request);
}
protected function getTenantFromCookie(string $cookie): string|null
{
// If the cookie looks like it's encrypted, we try decrypting it
if (str_starts_with($cookie, 'eyJpdiI')) {
try {
$json = base64_decode($cookie);
$data = json_decode($json, true);
if (
is_array($data) &&
isset($data['iv']) &&
isset($data['value']) &&
isset($data['mac'])
) {
// We can confidently assert that the cookie is encrypted. If this call were to fail, this method would just
// return null and the cookie payload would get skipped.
$cookie = CookieValuePrefix::validate(
static::$cookie,
Crypt::decryptString($cookie),
Crypt::getAllKeys()
);
}
} catch (\Throwable) {
// In case of any exceptions, we just use the original cookie value.
}
} elseif (static::$requireCookieEncryption) {
return null;
}
return $cookie;
}
}