diff --git a/src/Storageless/Http/SessionMiddleware.php b/src/Storageless/Http/SessionMiddleware.php index a0b8300e..d43bf7ec 100644 --- a/src/Storageless/Http/SessionMiddleware.php +++ b/src/Storageless/Http/SessionMiddleware.php @@ -35,7 +35,6 @@ use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface; -use PSR7Sessions\Storageless\Http\ClientFingerprint\Configuration as FingerprintConfig; use PSR7Sessions\Storageless\Http\ClientFingerprint\SameOriginRequest; use PSR7Sessions\Storageless\Session\DefaultSessionData; use PSR7Sessions\Storageless\Session\LazySession; @@ -63,7 +62,7 @@ public function __construct( */ public function process(Request $request, RequestHandlerInterface $handler): Response { - $sameOriginRequest = new SameOriginRequest($this->fingerprintConfig, $request); + $sameOriginRequest = new SameOriginRequest($this->config->getClientFingerprintConfiguration(), $request); $token = $this->parseToken($request, $sameOriginRequest); $sessionContainer = LazySession::fromContainerBuildingCallback(function () use ($token): SessionInterface { return $this->extractSessionContainer($token); @@ -179,7 +178,7 @@ private function getTokenCookie(SessionInterface $sessionContainer, SameOriginRe $jwtConfiguration = $this->config->getJwtConfiguration(); - $builder = $this->config->builder(ChainedFormatter::withUnixTimestampDates()) + $builder = $jwtConfiguration->builder(ChainedFormatter::withUnixTimestampDates()) ->issuedAt($now) ->canOnlyBeUsedAfter($now) ->expiresAt($expiresAt) @@ -191,7 +190,7 @@ private function getTokenCookie(SessionInterface $sessionContainer, SameOriginRe ->config->getCookie() ->withValue( $builder - ->getToken($this->config->signer(), $this->config->signingKey()) + ->getToken($jwtConfiguration->signer(), $jwtConfiguration->signingKey()) ->toString(), ) ->withExpires($expiresAt); diff --git a/src/Storageless/Http/SessionMiddlewareConfiguration.php b/src/Storageless/Http/SessionMiddlewareConfiguration.php index 2ad4c78c..42c066c9 100644 --- a/src/Storageless/Http/SessionMiddlewareConfiguration.php +++ b/src/Storageless/Http/SessionMiddlewareConfiguration.php @@ -25,6 +25,7 @@ use Lcobucci\Clock\Clock; use Lcobucci\Clock\SystemClock; use Lcobucci\JWT\Configuration; +use PSR7Sessions\Storageless\Http\ClientFingerprint\Configuration as FingerprintConfig; /** @immutable */ final class SessionMiddlewareConfiguration @@ -38,18 +39,20 @@ final class SessionMiddlewareConfiguration private int $refreshTime = 60; /** @var literal-string */ private string $sessionAttribute = SessionMiddleware::SESSION_ATTRIBUTE; + private FingerprintConfig $clientFingerprintConfiguration; public function __construct( Configuration $jwtConfiguration, ) { $this->jwtConfiguration = clone $jwtConfiguration; - $this->clock = SystemClock::fromSystemTimezone(); - $this->cookie = SetCookie::create('__Secure-slsession') + $this->clock = SystemClock::fromSystemTimezone(); + $this->cookie = SetCookie::create('__Secure-slsession') ->withSecure(true) ->withHttpOnly(true) ->withSameSite(SameSite::lax()) ->withPath('/'); + $this->clientFingerprintConfiguration = new FingerprintConfig(); } public function getJwtConfiguration(): Configuration @@ -85,6 +88,11 @@ public function getSessionAttribute(): string return $this->sessionAttribute; } + public function getClientFingerprintConfiguration(): FingerprintConfig + { + return $this->clientFingerprintConfiguration; + } + public function withJwtConfiguration(Configuration $jwtConfiguration): self { $new = clone $this; @@ -135,4 +143,12 @@ public function withSessionAttribute(string $sessionAttribute): self return $new; } + + public function withClientFingerprintConfiguration(FingerprintConfig $clientFingerprintConfiguration): self + { + $new = clone $this; + $new->clientFingerprintConfiguration = clone $clientFingerprintConfiguration; + + return $new; + } } diff --git a/test/StoragelessTest/Http/SessionMiddlewareConfigurationTest.php b/test/StoragelessTest/Http/SessionMiddlewareConfigurationTest.php index 17cc11d7..ccb3db78 100644 --- a/test/StoragelessTest/Http/SessionMiddlewareConfigurationTest.php +++ b/test/StoragelessTest/Http/SessionMiddlewareConfigurationTest.php @@ -27,6 +27,7 @@ use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\Key\InMemory; use PHPUnit\Framework\TestCase; +use PSR7Sessions\Storageless\Http\ClientFingerprint\Configuration as FingerprintConfig; use PSR7Sessions\Storageless\Http\SessionMiddlewareConfiguration; use function random_bytes; @@ -78,6 +79,13 @@ public function testProvideNonEmptyDefaultsForScalarAttributes(): void self::assertNotEmpty($config->getSessionAttribute()); } + public function testClientFingerprintConfigurationIsDisabled(): void + { + $config = new SessionMiddlewareConfiguration($this->jwtConfig); + + self::assertFalse($config->getClientFingerprintConfiguration()->enabled()); + } + public function testImmutability(): void { $leftConfig = new SessionMiddlewareConfiguration($this->jwtConfig); @@ -112,5 +120,11 @@ public function testImmutability(): void $leftConfig = $rightConfig->withSessionAttribute($sessionAttribute); self::assertNotSame($leftConfig, $rightConfig); self::assertSame($sessionAttribute, $leftConfig->getSessionAttribute()); + + $clientFingerprintConfiguration = FingerprintConfig::forIpAndUserAgent(); + $leftConfig = $rightConfig->withClientFingerprintConfiguration($clientFingerprintConfiguration); + self::assertNotSame($leftConfig, $rightConfig); + self::assertNotSame($clientFingerprintConfiguration, $leftConfig->getClientFingerprintConfiguration()); + self::assertSame($clientFingerprintConfiguration->sources(), $leftConfig->getClientFingerprintConfiguration()->sources()); } } diff --git a/test/StoragelessTest/Http/SessionMiddlewareTest.php b/test/StoragelessTest/Http/SessionMiddlewareTest.php index cb836b64..7ec866e3 100644 --- a/test/StoragelessTest/Http/SessionMiddlewareTest.php +++ b/test/StoragelessTest/Http/SessionMiddlewareTest.php @@ -538,12 +538,8 @@ public function testAllowCustomRequestAttributeName(): void public function testDefaultConfigurationShouldNotUseClientFingerprinting(): void { - $middleware = SessionMiddleware::fromSymmetricKeyDefaults( - self::makeRandomSymmetricKey(), - 100, - ); - $response = $middleware->process(new ServerRequest(), $this->writingMiddleware()); - $token = $this->getCookie($response)->getValue(); + $response = $this->middleware->process(new ServerRequest(), $this->writingMiddleware()); + $token = $this->getCookie($response)->getValue(); self::assertIsString($token); self::assertTrue($token !== ''); @@ -574,14 +570,7 @@ public function extractFrom(ServerRequestInterface $request): string }; $middleware = new SessionMiddleware( - Configuration::forSymmetricSigner( - new Sha256(), - self::makeRandomSymmetricKey(), - ), - SetCookie::create(SessionMiddleware::DEFAULT_COOKIE), - 100, - SystemClock::fromSystemTimezone(), - fingerprintConfig: new FingerprintConfig($source), + $this->config->withClientFingerprintConfiguration(new FingerprintConfig($source)), ); $request = new ServerRequest([$serverParamKey => $serverParamValue]); @@ -595,7 +584,7 @@ public function extractFrom(ServerRequestInterface $request): string self::assertInstanceOf(Plain::class, $parsedToken); self::assertTrue($parsedToken->claims()->has(SameOriginRequest::CLAIM)); - $validNewRequest = $request->withCookieParams([SessionMiddleware::DEFAULT_COOKIE => $token]); + $validNewRequest = $request->withCookieParams([$this->config->getCookie()->getName() => $token]); $middleware->process( $validNewRequest, @@ -613,7 +602,7 @@ static function (ServerRequestInterface $request) use ($sessionValue) { $invalidNewRequest = (new ServerRequest([ $serverParamKey => $serverParamValue . ' changed', - ]))->withCookieParams([SessionMiddleware::DEFAULT_COOKIE => $token]); + ]))->withCookieParams([$this->config->getCookie()->getName() => $token]); $middleware->process( $invalidNewRequest,