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

make token invalidation optional #14

Open
wants to merge 1 commit into
base: 1.6.x
Choose a base branch
from

Conversation

linusheske
Copy link

@linusheske linusheske commented Feb 22, 2022

Q A
Documentation no
Bugfix no
BC Break no
New Feature yes
RFC no
QA no

Description

In my opinion, invalidating a csrf token should be optional. The token is currently invalidated in the src/SessionCsrfGuard::validateToken method with each call. This is not always the desired behaviour. Especially when using the libary in legacy Applications.

References:
https://security.stackexchange.com/questions/22903/why-refresh-csrf-token-per-form-request/22936

For the reasons already discussed, it is not necessary to generate a new token per request. It brings almost zero security advantage, and it costs you in terms of usability: with only one token valid at once, the user will not be able to navigate the webapp normally. For example if they hit the 'back' button and submit the form with new values, the submission will fail, and likely greet them with some hostile error message. If they try to open a resource in a second tab, they'll find the session randomly breaks in one or both tabs.

https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#synchronizer-token-pattern

CSRF tokens should be generated on the server-side. They can be generated once per user session or for each request. Per-request tokens are more secure than per-session tokens as the time range for an attacker to exploit the stolen tokens is minimal. However, this may result in usability concerns. For example, the "Back" button browser capability is often hindered as the previous page may contain a token that is no longer valid. Interaction with this previous page will result in a CSRF false positive security event at the server. In per-session token implementation after initial generation of token, the value is stored in the session and is used for each subsequent request until the session expires.

@Ocramius Ocramius added Enhancement New feature or request RFC labels Feb 22, 2022
@Ocramius Ocramius requested a review from a team February 22, 2022 16:43
Signed-off-by: linusheske <heskelinus@yahoo.de>
@linusheske linusheske force-pushed the make_token_invalidation_optional branch from 8d9c3fb to 4a2c1c3 Compare February 22, 2022 16:44
@Ocramius
Copy link
Member

Seems OK-ish from my PoV: token could be invalidated after usage.

There is still a BC break though: currently, the behavior invalidates the token each time, which means that mezzio-csrf is precisely able to prevent form submit in some cases. That may be seen as a UX issue (like in this ticket) or as a feature (preventing usage of the same form on multiple browser tabs, for example), depending on PoV.

If this middleware is used only for preventing third-party XSS, then IMO Same-Site headers are a better alternative to the whole component 🤔

@@ -23,5 +23,5 @@ public function generateToken(string $keyName = '__csrf'): string;
*
* CSRF tokens should EXPIRE after the first hop.
*/
public function validateToken(string $token, string $csrfKey = '__csrf'): bool;
public function validateToken(string $token, string $csrfKey = '__csrf', bool $invalidateToken = true): bool;
Copy link
Member

Choose a reason for hiding this comment

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

This interface change is still a BC break though.

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.

None yet

2 participants