-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Refactor CSRF protection modules, make sure CSRF tokens can be up-to-date. #19337
Conversation
f0023a5
to
c6da09f
Compare
c6da09f
to
e3aa6b4
Compare
e3aa6b4
to
9c5b27b
Compare
69e6236
to
70f8710
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it would make sense to move this into a separate package?
modules/context/xsrf.go
Outdated
// It is exported so clients may set cookie timeouts that match generated tokens. | ||
const Timeout = 24 * time.Hour | ||
const CsrfTokenTimeout = 24 * time.Hour | ||
const CsrfTokenRegenerationDuration = 1 * time.Minute |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems far too frequent. Perhaps this should be hourly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems far too frequent. Perhaps this should be hourly?
It doesn't matter, it's just a simple hash when generating the token, doesn't cost more resources than other logic.
And the generated token is valid for the next 24 hours, so there should be no problem.
Indeed we can keep generating new tokens on every request, there will still be no performance problem. I just introduced this mechanism in case someone doesn't like generating the tokens (and sending cookies) again and again.
modules/context/csrf.go
Outdated
// If cookie token presents, re-use existing unexpired token, else generate a new one. | ||
if issueTime, ok := ParseCsrfToken(x.Token); ok { | ||
dur := time.Since(issueTime) | ||
if dur >= -CsrfTokenRegenerationDuration && dur <= CsrfTokenRegenerationDuration { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this really be negative?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this really be negative?
For example, the server time changed a lot? Personally I prefer to check the [-duration, duration]
range
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ps: if issueTime
can be guaranteed to be a monotonic clock, then we do not check the negative range. Checking the negative is not wrong because the issueTime might come from other packages and be refactored.
If you prefer to remove the negative check, it might can be done. However, I think it requires the code to store the mono clock in token, instead of a simple UnixNano ..... currently, issueTime := time.Unix(0, nanos)
is a non-monotonic clock
What's the preferred package name and package path? |
This comment was marked as off-topic.
This comment was marked as off-topic.
|
I do not think |
It's code to handle CSRF, seems pretty clear to me. And a short name is easy to work with. |
TBH, I still think the name And this PR has done what it should do. Moving code into a new package is too much for this PR. Reasons:
|
* giteaofficial/main: (22 commits) Add logic to switch between source/rendered on Markdown (go-gitea#19356) Fixed registry host value. (go-gitea#19363) [skip ci] Updated translations via Crowdin Allow package linking to private repository (go-gitea#19348) Use "main" as default branch name (go-gitea#19354) Move milestone to models/issues/ (go-gitea#19278) Refactor CSRF protection modules, make sure CSRF tokens can be up-to-date. (go-gitea#19337) Remove dependent on session auth for api/v1 routers (go-gitea#19321) API: Search Issues, dont show 500 if filter result in empty list (go-gitea#19244) [skip ci] Updated translations via Crowdin Never use /api/v1 from Gitea UI Pages (go-gitea#19318) [skip ci] Updated translations via Crowdin Show ssh command directly in template instead of i18n translation (go-gitea#19335) Package registry changes (go-gitea#19305) [skip ci] Updated translations via Crowdin Add `ENABLE_SSH_LOG` to debugging problems (go-gitea#19316) Warn on SSH connection for incorrect configuration (go-gitea#19317) escape fake link Allow custom redirect for landing page (go-gitea#19324) [skip ci] Updated translations via Crowdin ...
…date. (go-gitea#19337) Do a refactoring to the CSRF related code, remove most unnecessary functions. Parse the generated token's issue time, regenerate the token every a few minutes.
The CSRF protection modules have been broken for a while. For example, comment said:
// Csrfer maps CSRF to each request. If this request is a Get request, it will generate a new token.
, however, it doesn't!! That's why a lot of users complain about their work lost.Related issues:
And maybe more.
This PR does a refactoring to the CSRF related code, removes most unnecessary functions.
It introduces
ParseCsrfToken
to parse the generated token's issue time, and regenerate the token every minute.And it fixes some incorrect code in old code, for example:
ctx.Data["CsrfToken"] = html.EscapeString(ctx.csrf.GetToken())
, theEscapeString
is incorrect.The error handling logic in
Validate
has been simplified, remove many duplicate code.Totally this PR is
+119 −195