Skip to content
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

fix: Security class sends cookies immediately #5429

Merged
merged 15 commits into from
Dec 8, 2021

Conversation

kenjis
Copy link
Member

@kenjis kenjis commented Dec 2, 2021

Description
Fixes #5406

  • move secure cookie check from Security to ResponseTrait
  • Security class does not send cookie, just set it to Response
  • CookieStore class does not send cookies, Response sends cookies
  • Response::setCookie() can get Cookie object now
  • deprecated
    • CookieStore::dispatch()
    • CookieStore::setRawCookie()
    • CookieStore::setCookie()
    • Security::sendCookie()
    • Security::doSendCookie()

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

@kenjis kenjis added the bug Verified issues on the current code behavior or pull requests that will fix them label Dec 2, 2021
@MGatner
Copy link
Member

MGatner commented Dec 2, 2021

This adds a new dependency (Cookie on Security), which is fine but it must be defined in depfile.yaml.

@lonnieezell
Copy link
Member

Does this need to handle the setRawCookie (?) method from the security class also?

Copy link
Member

@paulbalandan paulbalandan left a comment

Choose a reason for hiding this comment

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

Looking at the previous dependency addition warning, I think the SecurityException should not be inside the CookieStore class. IMO, CookieStore should be clean from outside dependencies and just dispatch the cookies in its collection. No outside interference.

The addition of setCookieStore() method in Response looks good to me. Reading on the related issue, my suggestion would be:

  1. On sending the CSRF cookie, Security gets the saved instance of the CookieStore from the Response then save to it the CSRF cookie.
  2. Security still retains the secure checks on the cookie.
  3. Security puts the new CookieStore instance to the Response using $response->setCookieStore($cookieStore);
  4. Response, after saving the new cookie store instance, invokes sendCookies() via the send() method. This calls $cookieStore->dispatch()
  5. CookieStore will send all the cookies in its store, including the CSRF cookie.

@kenjis
Copy link
Member Author

kenjis commented Dec 3, 2021

@lonnieezell

Does this need to handle the setRawCookie (?) method from the security class also?

What do you mean?

@kenjis
Copy link
Member Author

kenjis commented Dec 3, 2021

@paulbalandan

I think it is weird that CookieStore dispatches cookies.
Response should dispatch cookies.
But if do so, it seems breaking changes.

Your opinion is just moving the secure checks on the cookie back to Security, right?

@kenjis
Copy link
Member Author

kenjis commented Dec 3, 2021

Response should dispatch cookies.
But if do so, it seems breaking changes.

I thought that. But it seems I could go.
I moved dispatching cookie from CookieStore to Respose.

@kenjis kenjis marked this pull request as draft December 4, 2021 00:49
@kenjis kenjis marked this pull request as ready for review December 4, 2021 01:48
@MGatner
Copy link
Member

MGatner commented Dec 4, 2021

It looks like @paulbalandan has a better grasp on this so I will not review. Thanks for the work though, I assume this fixes the test case issues.

Copy link
Member

@paulbalandan paulbalandan left a comment

Choose a reason for hiding this comment

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

I've looked at how other frameworks send cookies. Particularly, for CakePHP, they send cookies using the ResponseEmitter class so I think this is good. In the future, or future versions, I think we can also modularize class responsibilities.

@kenjis
Copy link
Member Author

kenjis commented Dec 7, 2021

I rebased for just signing commits.

@kenjis
Copy link
Member Author

kenjis commented Dec 7, 2021

I will add the documentation.

Comment on lines +533 to +535
/** @var Response $response */
$response = Services::response();
$response->setCookie($this->cookie);
Copy link
Contributor

@mostafakhudair mostafakhudair Dec 7, 2021

Choose a reason for hiding this comment

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

Any point of storing response service in a variable?

Suggested change
/** @var Response $response */
$response = Services::response();
$response->setCookie($this->cookie);
Services::response()->setCookie($this->cookie);

Copy link
Member Author

Choose a reason for hiding this comment

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

To explicitly indicate dependency.
This is also to avoid disabling the deptrac check.

You may like the short code, but it hides the dependency Response.
deptrac can't detect it.

Services::response()->setCookie($this->cookie);

@kenjis
Copy link
Member Author

kenjis commented Dec 8, 2021

I added the documentation.
Can someone review?

@kenjis kenjis merged commit 76ad2ad into codeigniter4:develop Dec 8, 2021
@kenjis kenjis deleted the fix-security-sends-cookies branch December 8, 2021 06:30
@MGatner
Copy link
Member

MGatner commented Dec 10, 2021

💪

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Verified issues on the current code behavior or pull requests that will fix them
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug: Security class sends cookies immediately, instead of coordinating with the Response class.
5 participants