-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Add start of state to CSRF cookie name #1504
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
Conversation
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 think this is a good improvement to the project on first glance, but it would be good to seem some tests and maybe make the code a bit easier to read if possible
pkg/cookies/csrf.go
Outdated
| cookie, err := req.Cookie(csrfCookieName(opts)) | ||
|
|
||
| // csrfCookieName will include state to have multiple csrf in case of parallel requests | ||
| state := req.URL.Query()["state"][0][0:csrfStateLength - 1] |
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.
Is there a way we can make this a bit nicer to read and also handle the possibility of index out of bounds errors? Wondering what happens if state isn't there for example, or for some reason it ends up empty
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'm also curious if we can potentially manage multiple CSRF state checks in an array structure serialized in 1 CSRF struct serialized into the cookie?
Things on my mind:
- The cookie manages the OIDC nonce across requests too. How will that handle multiple (seems fine).
- We encrypt the cookie payload (oauth state & nonce contents). Making the state part of the cookie name will slightly weaken that posture. But I bet it's fine, the encryption was likely overkill and those would only expose a portion of the OAuth state nonce.
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'm also not convinced the multiple tab issue was the sole source of these intermittent CSRF failures.
At my previous company where I ran this in production, whenever users reported this error (and when it happened to me) multiple tabs logging in a once was never a symptom.
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 long running issue has more samples of tips people have (and theories on why this happens): #817
Do we think think this will fix some of the prefetch, favicon & JS issues people have uncovered as reasons?
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.
Hi @JoelSpeed, Added some more testing for edge cases.
@NickMeves I'm not sure about the multiple tabs, I have to say that from my experience, issues with multiple tabs can result from session management problems on the provider side.
I do suspect the parallel requests to favicon and prefetch are related to this.
pkg/cookies/csrf.go
Outdated
| func csrfCookieName(opts *options.Cookie) string { | ||
| return fmt.Sprintf("%v_csrf", opts.Name) | ||
| func csrfCookieName(opts *options.Cookie, state string) string { | ||
| return fmt.Sprintf("%v_%v_csrf", opts.Name, state) |
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.
NIT -- can we potentially flip these so the dynamic part of the cookie name is the suffix? (%v_csrf_%v). And it might be worth renaming the state variable to signify this is a subset of the state.
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.
In the CHANGELOG we will also need to signify this is potentially breaking for any users that had the cookieName option set close to the maximum (255 characters right?) -- Although I hope no one did that 🤣
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.
@NickMeves Sure. Fixed both
|
Hello @YoavOst , |
|
@NickMeves @JoelSpeed @YoavOst Anyway other people can help get this reviewed and merged faster? At work we're also running into the parallel Ajax problem which is currently blocking |
any updates guys? |
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.
Has anyone tested this at all? Looking at the PR there are no test changes, can we make sure there are unit tests to ensure we don't regress on this functionality in the future?
|
I've tested the PR, and can confirm that it solves the 403 FORBIDDEN problem. Thank you for that! However, when the oauth2 session is expired, CSRF cookies are issued for every request made. The only CSRF cookie that's cleaned up is the one leading to a successful oauth2 login. This in turn leads to large headers containing all the uncleaned cookies being sent by the browser, and eventually to requests running into max header size. |
|
Hello all! Since we would be very happy about this PR in a project, could someone please resolve this merge conflict? |
|
We suffer from the #817 so happy to test this as the merge conflict is fixed. |
|
In face of multiple oauth2 proxy callbacks, the CSRF cookie faces several concurrency problems:
This fix seems to solve both issues #1451 and #817 which have more than 2 years. Can conflits be fixed? |
|
This pull request has been inactive for 60 days. If the pull request is still relevant please comment to re-activate the pull request. If no action is taken within 7 days, the pull request will be marked closed. |
|
Let's give this a go, hopefully this resolves the issues. It would be nice if someone could follow up with some unit tests for this |
|
Ok this doesn't seem like it's working correctly as it's causing a panic within the tests, anyone got time to work out why and resolve that? |
|
Hello @JoelSpeed , |
|
May I suggest the branch from @mazenaissa #1708 . |
|
I'm going to close this in favour of #1708 as I think that's pretty much ready to go and seems to have had a bunch of testing from others |
Description
This change adds a part of the state nonce to the CSRF name, making it possible to have parallel callback requests.
When having parallel ajax requests after the session cookie has expired multiple callbacks occur at the same time, creating multiple CSRF tokens with the name making it impossible for the proxy to authenticate.
It solves issue 1451 and possibly issue 817
How Has This Been Tested?
Deployed using docker-compose with OIDC (keycloak) provider and cookie session store and solve the parallel AJAX requests issue.