Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[HttpFoundation][HttpKernel] Configure session.cookie_secure earlier #40231

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

Merged
merged 1 commit into from
Feb 25, 2021

Conversation

tamcy
Copy link
Contributor

@tamcy tamcy commented Feb 18, 2021

Q A
Branch? 4.4
Bug fix? yes
New feature? no
Deprecations? no
Tickets Fix #40221
License MIT
Doc PR N/A

This PR does what @stof had suggested in #40221, allow me to quote him directly:

  1. avoid setting auto as a value for the ini setting in the NativeSessionStorage initialization
  2. ensuring that SessionListener resolves the auto value by the time the SessionListener runs, and not by the time the getSession() method is called in the Request session factory callback

@carsonbot
Copy link

Hey!

I see that this is your first PR. That is great! Welcome!

Symfony has a contribution guide which I suggest you to read.

In short:

  • Always add tests
  • Keep backward compatibility (see https://symfony.com/bc).
  • Bug fixes must be submitted against the lowest maintained branch where they apply (see https://symfony.com/releases)
  • Features and deprecations must be submitted against the 5.x branch.

Review the GitHub status checks of your pull request and try to solve the reported issues. If some tests are failing, try to see if they are failing because of this change.

When two Symfony core team members approve this change, it will be merged and you will become an official Symfony contributor!
If this PR is merged in a lower version branch, it will be merged up to all maintained branches within a few days.

I am going to sit back now and wait for the reviews.

Cheers!

Carsonbot

@carsonbot carsonbot added the Bug label Feb 18, 2021
@derrabus derrabus changed the base branch from 5.x to 4.4 February 18, 2021 07:09
@derrabus derrabus added this to the 4.4 milestone Feb 18, 2021
@carsonbot carsonbot changed the title Cookie secure fix #40221 [HttpFoundation][HttpKernel] Cookie secure fix #40221 Feb 18, 2021
Copy link
Member

@jderusse jderusse left a comment

Choose a reason for hiding this comment

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

I think this PR works in your case because your php.ini file has cookie_secure=on and this PR prevent overriding the .ini value with "auto".

But what if your .ini is set to on and you call the page with http does it removes the cookie_secure flag? Or what if the .ini is set to off and the page is called with https is it re-added?

I believe we should disable the .ini setting when value is auto then the SessionListener will re-enabled it if the request is secured.

Are you sure that your Code/EventListener has a lower priority than the SessionListener and you are not reading the session before the flag is correctly sets?

Note: In Symfony 5.3, injecting the session in your service will be deprecated and you'll have to use the RequestStack to get a session. So this will not be an issue anymore, as you won't be able to manipulate the session before the SessionListener initialize the storage and inject the session in the request.

@tamcy
Copy link
Contributor Author

tamcy commented Feb 18, 2021

I think this PR works in your case because your php.ini file has cookie_secure=on and this PR prevent overriding the .ini value with "auto".

But 'auto' is not a valid value for this ini setting. Yes, setting cookie_secure=auto via ini_set does have the same effect as setting it to false/off/0, but the question is whether this is an intended behavior. For this I agree with @stof that the value 'auto' shouldn't be passed as-is to the session storage.

But what if your .ini is set to on and you call the page with http does it removes the cookie_secure flag? Or what if the .ini is set to off and the page is called with https is it re-added?

You are correct that this PR missed the scenario when the page is accessed through http, not https. The code only sets cookie_secure to true for https, but didn't set it to false for http traffic. In this case the onKernelRequest callback could be changed to something like this:

        if ($this->container->has('session_storage')
            && ($storage = $this->container->get('session_storage')) instanceof NativeSessionStorage
            && ($masterRequest = $this->container->get('request_stack')->getMasterRequest())
        ) {
            $storage->setOptions(['cookie_secure' => $masterRequest->isSecure()]);
        }

I believe we should disable the .ini setting when value is auto then the SessionListener will re-enabled it if the request is secured.

Personally I don't have preference on whether the setting is set in one place, or is first disabled then enabled if the traffic in https. But again, I think the value passed to ini_set shouldn't be 'auto'.

Are you sure that your Code/EventListener has a lower priority than the SessionListener and you are not reading the session before the flag is correctly sets?
Note: In Symfony 5.3, injecting the session in your service will be deprecated and you'll have to use the RequestStack to get a session. So this will not be an issue anymore, as you won't be able to manipulate the session before the SessionListener initialize the storage and inject the session in the request.

I need to confess that my experience with Symfony internals isn't deep enough for me to guarantee that people will be immune from similar situations. They may still able to register an event listener which accesses the session before SessionListener is called, causing it to fail to properly set the cookie_secure flag (actually there might even be a need to tell the developer that the service cannot set the flag properly, given this is a security related thing). But, for my case, what I did was just registering a guard authenticator which accesses session data in the supports() method. I didn't change the priority of any of the involved services. And by default the authenticator's supports() is called before SessionListener.

@stof
Copy link
Member

stof commented Feb 18, 2021

And by default the authenticator's supports() is called before SessionListener.

no it is not. And that's precisely why this PR will fix the issue by making sure that the auto value is resolved by the time SessionListener is called (rather than by the time the session is retrieved from the Request object for the first time)

@tamcy tamcy force-pushed the cookie-secure-fix-40221 branch from 0016095 to 519eb1c Compare February 19, 2021 04:13
@tamcy
Copy link
Contributor Author

tamcy commented Feb 19, 2021

@stof is right. I forgot to update my mind when writing the reply.

The PR has been updated. In this PR,

  1. Instead of letting NativeSessionStorage to check for this auto value in the cookie_secure key and act differently, the framework will create another set of options that does not contain the secure_cookie option if it is set to auto, and the NativeSessionStorage will receive this special set of options in the constructor.

  2. The SessionListener class is updated to set the cookie_secure value properly in onKernelRequest, no matter the request is secure or not. This fixes the issue in the previous PR that cookie_secure won't be set if the request is not secure.

Two related notes:

  1. The scope of the issue is actually larger then I anticipated. Just create a new application, add a simple controller action that accesses the session. The auto secure cookie won't work because of the reason explained by @stof.

  2. I have also verifitied that after the PR, user can still "invalidate" the SessionListener by creating an event listener that accesses the session with priority equal to or higher than that of SessionListener like this.

@nicolas-grekas nicolas-grekas changed the title [HttpFoundation][HttpKernel] Cookie secure fix #40221 [HttpKernel] Configure session.cookie_secure earlier Feb 25, 2021
@nicolas-grekas nicolas-grekas force-pushed the cookie-secure-fix-40221 branch from 519eb1c to e82918c Compare February 25, 2021 17:13
Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

(implem updated a bit)

@carsonbot carsonbot changed the title [HttpKernel] Configure session.cookie_secure earlier [HttpFoundation][HttpKernel] Configure session.cookie_secure earlier Feb 25, 2021
@nicolas-grekas
Copy link
Member

Thank you @tamcy.

@nicolas-grekas nicolas-grekas merged commit 87aeb8d into symfony:4.4 Feb 25, 2021
@stof
Copy link
Member

stof commented Feb 25, 2021

2\. I have also verifitied that after the PR, user can still "invalidate" the `SessionListener` by creating an event listener that accesses the session with priority equal to or higher than that of `SessionListener` [like this](https://github.com/tamcy/symfony-secure-cookie-test-4.4/blob/master/src/EventListener/NullifyAutoCookieSecureEventListener.php).

this is fine to me. On future versions where accessing the session as a service is not possible anymore, you won't be able to access the session before it is initialized in the Request by SessionListener (which is also why it runs at priority 100)

@tamcy
Copy link
Contributor Author

tamcy commented Feb 28, 2021

@nicolas-grekas Thank you. May I know if it is intentional to use my first pull request, rather than the second one? I ask this because besides the difference in approach, the second PR includes a fix in the SessionListener which is missing in the first PR. In the first (merged) PR, the code reads:

        if ($this->container->has('session_storage')
            && ($storage = $this->container->get('session_storage')) instanceof NativeSessionStorage
            && ($masterRequest = $this->container->get('request_stack')->getMasterRequest())
            && $masterRequest->isSecure()
        ) {
            $storage->setOptions(['cookie_secure' => true]);
        }

In this code, if the request is not https, the storage option will not be set. Consequently, the default PHP value will be used. If the default ini value is set to On (forcing secure cookie), the cookie will not work in an auto environment. Which is why the the code in the second PR, the code is changed to:

       if ($this->container->has('session_storage')
            && ($storage = $this->container->get('session_storage')) instanceof NativeSessionStorage
            && ($masterRequest = $this->container->get('request_stack')->getMasterRequest())
        ) {
            $storage->setOptions(['cookie_secure' => $masterRequest->isSecure()]);
        }

Please advise what could be done. Shall I create another PR for this? Thank you!

@nicolas-grekas
Copy link
Member

Yes, I reverted that part because I thought it was not desired: the goal here is to upgrade to ssl when possible. Never to downgrade to no-ssl, which is what the change you're mentioning would do to me.

@tamcy
Copy link
Contributor Author

tamcy commented Feb 28, 2021

I see, thank you, this makes sense. Do we need a warning to users though? As this kind of downgrade does happen before the patch (the value is always set to "auto" at first, which effectively turns off the secure cookie flag).

This was referenced Mar 4, 2021
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.

In auto mode, cookie_secure may not be set properly in a secure environment if session starts too soon
6 participants