Skip to content

[Security] Make statefull pages NOT turn responses private when the token is not used #28089

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

nicolas-grekas
Copy link
Member

@nicolas-grekas nicolas-grekas commented Jul 30, 2018

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #26769 et al.
License MIT
Doc PR -

Replaces #27817
By taking over session usage tracking and replacing it with token usage tracking, we can prevent responses that don't actually use the token from turning responses private without changing anything to the lifecycle of security listeners. This makes the behavior much more seamless, allowing to still log the user with the monolog processor, and display it in the profiler toolbar.

@nicolas-grekas
Copy link
Member Author

nicolas-grekas commented Jul 30, 2018

Now tested and green, ready.

@@ -30,7 +30,7 @@ public function __construct(TokenStorageInterface $tokenStorage)
public function __invoke(array $records)
{
$records['extra']['token'] = null;
if (null !== $token = $this->tokenStorage->getToken()) {
if (null !== $token = $this->tokenStorage->getToken(false)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the feeling this is a step backwards in terms of code quality 😢

When I see this and then look at the interface I'm confused:

https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorageInterface.php#L28

So here we kind of code against the implementation UsageTrackingTokenStorage and not against the abstraction/interface anymore.

Copy link
Contributor

@dmaicher dmaicher Jul 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also if someone decorated the original security.token_storage service this will not work properly, right? (as the argument will be missing in any parent::getToken() call because its simply not part of the contract).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we kind of code against the implementation UsageTrackingTokenStorage

fixed by adding a new UsageTrackingTokenStorageInterface

if someone decorated the original security.token_storage service this will not work properly, right?

The behavior will be the same as currently. That's the typical downside with service decoration: you're required to adapt to changes done at the decorated level. It's not very different from being required to write new code to leverage any new features. There is no way around.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the issue here is that your new interface adds a new argument to the same method, making it really weird for decorators

Copy link
Member Author

@nicolas-grekas nicolas-grekas Aug 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what/why this is weird. This works fine.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stof I think that's OK. We don't want ppl to have to use two different methods for fetching the token. And this is in a separate interface (UsageTrackingTokenStorageInterface) so that's documented. We don't want ppl to decorate blindly btw.

@nicolas-grekas
Copy link
Member Author

I'm putting this on-hold because I think we can get rid of the UsageTrackingTokenStorageInterface.

Status: needs work

@fabpot
Copy link
Member

fabpot commented Sep 26, 2018

Any news on this one? Can we close #27817?

@nicolas-grekas
Copy link
Member Author

Not yet, I'll keep you posted.

@nicolas-grekas nicolas-grekas changed the base branch from master to 4.4 June 2, 2019 20:04
@Plopix
Copy link
Contributor

Plopix commented Sep 7, 2019

hello, I have just encountered this "issue".
Something is starting the session even if we don't use it which triggers private page. (Firewall?)

Which is not cool for performances :D

My current workaround if (useful for others) is a listener where I disabled this feature for now

public function onKernelResponse(ResponseEvent $event): void
    {
        $event->getResponse()->headers->set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER, 'true');
    }

Note that I agree with the concept when this will work.

If we read the session, then that's private. That makes sense ;) (but only if we really read it)

@wadjeroudi
Copy link

@nicolas-grekas using the usageIndex, seems like a hack. Could it be better to load/start the session only when the token is really used ?
The token would be a callback that would load/unserialize the token only if "getted". So the session won't start if nobody uses the token.

@nicolas-grekas
Copy link
Member Author

@wadjeroudi that wouldn't work as soon as subrequests are involved, especially when HttpCache is used with ESI.

@nicolas-grekas
Copy link
Member Author

Continued in #33663, please review there now.

@nicolas-grekas nicolas-grekas deleted the sec-dis-track branch September 22, 2019 20:58
fabpot added a commit that referenced this pull request Sep 24, 2019
…ate only when needed (nicolas-grekas)

This PR was merged into the 4.4 branch.

Discussion
----------

[Security] Make stateful firewalls turn responses private only when needed

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #26769 *et al.*
| License       | MIT
| Doc PR        | -

Replaces #28089

By taking over session usage tracking and replacing it with token usage tracking, we can prevent responses that don't actually use the token from turning responses private without changing anything to the lifecycle of security listeners. This makes the behavior much more seamless, allowing to still log the user with the monolog processor, and display it in the profiler toolbar.

This works by using two separate token storage services:
- `security.token_storage` now tracks access to the token and increments the session usage tracker when needed. This is the service that is injected in userland.
- `security.untracked_token_storage` is a raw token storage that just stores the token and is disconnected from the session. This service is injected in places where reading the session doesn't impact the generated output in any way (as e.g. in Monolog processors, etc.)

Commits
-------

20df3a1 [Security] Make stateful firewalls turn responses private only when needed
@nicolas-grekas nicolas-grekas modified the milestones: next, 4.4 Oct 27, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants