fix: Sanctum middleware config mutation#387
Merged
Merged
Conversation
Replaces the subclass-based getSessionCookieConfig() override with a static callback registry. Callbacks run in registration order, each receiving the previous callback's output. Threads Request through to the resolver so callbacks can vary cookie attributes per-request without mutating worker-global config.
Replaces the subclass-override test with four callback tests covering single-callback registration, per-request behavior via Request, chained composition in registration order, and flushState clearing the registry. Switches base class to Hypervel\Tests\TestCase and the reflection helper to ClassInvoker.
Prevents the new StartSession cookie callback registry and SanctumGuard Macroable state from leaking between tests.
Adds a Configuring the Session Cookie section covering the new StartSession callback API, its boot-time registration pattern, and chained registration semantics.
Drops the unconditional config([...]) mutation that fired on every request through this middleware. Under Swoole the mutation persisted on the worker-global config singleton and leaked across concurrent requests. Cookie hardening is now applied via a StartSession callback registered by SanctumServiceProvider.
Replaces the runtime config mutation with a boot-time configureSessionCookieUsing callback that forces http_only=true and same_site=lax only when the request has the sanctum attribute set by EnsureFrontendRequestsAreStateful's prepended inline middleware.
SanctumGuard is effectively a worker-lifetime singleton (cached in AuthManager's guards registry, and AuthManager is itself a singleton). Without flushState, macros registered on the Macroable trait persisted across tests and across coroutines for the worker lifetime.
Sets session.http_only=false and session.same_site=strict to non-default values, runs EnsureFrontendRequestsAreStateful, and asserts both values are still unchanged. Catches any regression that reintroduces the removed configureSecureCookieSessions config([...]) call.
Covers three contracts: stateful Sanctum frontend requests force http_only=true and same_site=lax on the session cookie; app-level StartSession callbacks compose with Sanctum's hardening; non-Sanctum requests bypass the hardening based on the sanctum request attribute.
Locks in that SanctumGuard::flushState() clears Macroable-registered macros, guarding the test-isolation contract for the worker-lifetime singleton guard.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR cleans up Sanctum so it no longer mutate's configuration per-request. It also refactor's the previous extension point we added to a static method so it can be set in a service provider.
Summary
StartSession::configureSessionCookieUsing()so session cookie attributes can be customized per request from a service provider, without subclassing the session middleware.SanctumGuardmacros, with regression coverage for cookie hardening, callback composition, and test isolation.Details
Sanctum previously called
config()fromEnsureFrontendRequestsAreStateful::handle()to forcesession.http_only = trueandsession.same_site = lax. That is safe in Laravel's request model, but not in Hypervel workers: the config repository is process-global, so request-time writes can leak into other requests handled by the same worker. Technically it wasn't causing problems but it's a worthwhile correctness cleanup.This PR keeps Sanctum's behavior without the global mutation.
StartSessionnow supports boot-time registration of request-aware cookie configuration callbacks:Callbacks run when the session cookie is written, receive the current request and current cookie configuration, and compose in registration order. Sanctum registers one of these callbacks during provider boot and only applies its
http_only/same_sitehardening when the existing Sanctum request attribute is present.This also replaces the older protected-method extension point. Customizing session cookie attributes no longer requires creating a child middleware class and swapping it into the middleware stack; apps can now configure the behavior directly from a service provider, which is closer to Laravel's
...Using()extension style and easier to use for multi-tenant cookie settings.Tests
./vendor/bin/phpunit tests/Session/Middleware/StartSessionTest.php./vendor/bin/phpunit tests/Session./vendor/bin/phpunit tests/Sanctum/EnsureFrontendRequestsAreStatefulTest.php tests/Sanctum/FrontendCookieHardeningTest.php tests/Sanctum/SanctumGuardStaticStateTest.php./vendor/bin/phpunit tests/Sanctum./vendor/bin/phpunit tests/Session tests/Sanctum./vendor/bin/phpstan analyse src/session/src src/sanctum/src tests/Session/Middleware/StartSessionTest.php tests/Sanctum tests/AfterEachTestSubscriber.php