-
-
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
Automatically set cookie secure
attribute, remove COOKIE_SECURE option
#26953
Conversation
35ee675
to
c07c129
Compare
c07c129
to
c9cd3bf
Compare
}) | ||
handler(next).ServeHTTP(resp, req) | ||
}) | ||
} |
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.
Not 100% sure this usage is correct, but it appears to work.
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.
The "next" call is right, but the Sessioner is not designed to be used like this. eg: It starts a GC goroutine for every session.Sessioner()
call.
The sessioner expects there should be only one instance for all requests.
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.
If this is suboptimal, I think the only other option is to let sessioner accept a func
for the Secure
attribute as well, or add a autoSecure
option. Or look for alternative sessioners that are more flexible.
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.
It's not only suboptimal, it breaks the Sessioner's design and would cause bugs. The Sessioner also has many internal states, it expects the only one instance do "Init" (eg: connect to redis) and do session management (eg: Lock, GC).
Although we could make some changes to make a Sessioner work with dynamic Cookie Secure option, but I think it's too complex to do that, and "dynamic Cookie Secure" doesn't seem really bring enough benefit.
The mentioned "AppURL + COOKIE_SECURE option" should be simple enough and I don't see any problem by doing 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.
It's not just cookie secure. If the backend wants for example to reconstruct the original URL a client used (for example for audit log), XFP is required for that as well.
Maybe I'll look into sessioner accepting a function (typecheck with Reflect), that seems the simplest option.
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.
If the backend wants for example to reconstruct the original URL a client used (for example for audit log), XFP is required for that as well.
Just use AppURL, in many cases, the backend doesn't have the HTTP request context.
So, AppURL should always be correct.
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.
Unless the app runs on multiple URLs :)
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.
Unless the app runs on multiple URLs :)
Yup, but the AppURL should also be correct in this case, otherwise the nofication/mail/webhook would stop working.
As long as the AppURL should be always right, then just use it.
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 confirm on a instance behind reverse proxy that all cookies now have the |
// GetCookieSecure returns whether the "Secure" attribute on a cookie should be set | ||
func GetCookieSecure(req *http.Request) bool { | ||
forwardedProto := strings.ToLower(req.Header.Get("x-forwarded-proto")) | ||
if forwardedProto != "" { | ||
return forwardedProto == "https" || forwardedProto == "wss" | ||
} | ||
return req.TLS != nil | ||
} |
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.
Sorry but it's not right.
Many users might not pass these header when they use Gitea behind a reverse proxy.
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.
Maybe we can just parse setting.AppURL
.
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.
Maybe we can just parse
setting.AppURL
.
Yes. And:
- Keep the COOKIE_SECURE option, in case some people really would like to run Gitea on different domains
- COOKIE_SECURE should be default to true if AppURL is "https"
- Show a frontend warning if the "http" doesn't match COOKIE_SECURE=true, to tell users that "you might not be able to login"
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.
Many users might not pass these header when they use Gitea behind a reverse proxy.
At least for nginx, we have been documenting for a long time to configure that header.
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.
Yes, only "At least". None of others are documented.
And even there is a document, many users do not follow that, they just like to write the config by their experiences.
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 would call it out in changelog and be done with it. It's the right way to check if connection is secure imho.
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.
Thought I do see parsing AppURL
as the more forgiving option. In an application that does not have such a setting, the current method is the only one that can work, but given that we have AppURL
we might as well use it.
What only works with my method is to host the application on multiple domains and/or mixed http/https but I guess that is a seldomly used configuration.
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 prefer the solution in comment #26953 (comment) .
According to MDN, the X-Forwarded-Proto
is not standard and there are many alternatives (Front-End-Https
/ X-Forwarded-Protocol
/ X-Forwarded-Ssl
/ X-Url-Scheme
). IMO using the strong assumption with X-Forwarded-Proto
might cause many users unable to login and fail silently. Gitea should be able to be easy to setup and use out-of-box.
My suggestion also works well with "host the application on multiple domains and/or mixed http/https", the site admin could set COOKIE_SECURE=false in their config, keep trusted HTTP requests and redirect untrusted HTTP requests to HTTPS, still no security risk.
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.
So in summary: Keep COOKIE_SECURE
but the AppUrl is https, switch it to true? I'm not sure such "magic" is good to do. Maybe I should just scrap the entire PR.
So unless we agree on taking this up as an acceptable change and likely break a few setups with misconfigured reverse proxies, I won't continue here. I still think it's right to require a properly configured |
Breaking label added. |
Actually I think it's non-breaking for the most common setup where Gitea is running on http with a reverse proxy terminating https. The |
It is Update: I mean, the users who do not have proper "X-Forwarded-Proto" header is under the risk of not having "secure cookie", but they couldn't know it. It leaves a new security problem. |
Yes, the sessioner topic needs to be properly fixed first: https://gitea.com/go-chi/session/issues/7. |
I lost motivation here, if someone wants to do the AppURL parsing, please raise a separate PR, I'm not really interested in doing that. |
-> Use secure cookie for HTTPS sites #26999 |
The idea is to automatically set cookie
Secure
flag based on proxy headers or the connection, making it unnecessary to configure it by hand via previousCOOKIE_SECURE
option.Gitea now requires a properly configured
X-Forwarded-Proto
header from reverse proxies, which should be set at the first user-facing reverse proxy and not be changed by any additional proxies in the chain.