mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
* chore: rename `AgentConn` to `WorkspaceAgentConn` The codersdk was becoming bloated with consts for the workspace agent that made no sense to a reader. `Tailnet*` is an example of these consts. * chore: remove `Get` prefix from *Client functions * chore: remove `BypassRatelimits` option in `codersdk.Client` It feels wrong to have this as a direct option because it's so infrequently needed by API callers. It's better to directly modify headers in the two places that we actually use it. * Merge `appearance.go` and `buildinfo.go` into `deployment.go` * Merge `experiments.go` and `features.go` into `deployment.go` * Fix `make gen` referencing old type names * Merge `error.go` into `client.go` `codersdk.Response` lived in `error.go`, which is wrong. * chore: refactor workspace agent functions into agentsdk It was odd conflating the codersdk that clients should use with functions that only the agent should use. This separates them into two SDKs that are closely coupled, but separate. * Merge `insights.go` into `deployment.go` * Merge `organizationmember.go` into `organizations.go` * Merge `quota.go` into `workspaces.go` * Rename `sse.go` to `serversentevents.go` * Rename `codersdk.WorkspaceAppHostResponse` to `codersdk.AppHostResponse` * Format `.vscode/settings.json` * Fix outdated naming in `api.ts` * Fix app host response * Fix unsupported type * Fix imported type
73 lines
2.4 KiB
Go
73 lines
2.4 KiB
Go
package httpmw
|
|
|
|
import (
|
|
"net/http"
|
|
"regexp"
|
|
|
|
"github.com/justinas/nosurf"
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/coder/coder/codersdk"
|
|
)
|
|
|
|
// CSRF is a middleware that verifies that a CSRF token is present in the request
|
|
// for non-GET requests.
|
|
func CSRF(secureCookie bool) func(next http.Handler) http.Handler {
|
|
return func(next http.Handler) http.Handler {
|
|
mw := nosurf.New(next)
|
|
mw.SetBaseCookie(http.Cookie{Path: "/", HttpOnly: true, SameSite: http.SameSiteLaxMode, Secure: secureCookie})
|
|
mw.SetFailureHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
http.Error(w, "Something is wrong with your CSRF token. Please refresh the page. If this error persists, try clearing your cookies.", http.StatusBadRequest)
|
|
}))
|
|
|
|
// Exempt all requests that do not require CSRF protection.
|
|
// All GET requests are exempt by default.
|
|
mw.ExemptPath("/api/v2/csp/reports")
|
|
|
|
// Top level agent routes.
|
|
mw.ExemptRegexp(regexp.MustCompile("api/v2/workspaceagents/[^/]*$"))
|
|
// Agent authenticated routes
|
|
mw.ExemptRegexp(regexp.MustCompile("api/v2/workspaceagents/me/*"))
|
|
// Derp routes
|
|
mw.ExemptRegexp(regexp.MustCompile("derp/*"))
|
|
|
|
mw.ExemptFunc(func(r *http.Request) bool {
|
|
// Enable CSRF in November 2022 by deleting this "return true" line.
|
|
// CSRF is not enforced to ensure backwards compatibility with older
|
|
// cli versions.
|
|
//nolint:revive
|
|
return true
|
|
|
|
// CSRF only affects requests that automatically attach credentials via a cookie.
|
|
// If no cookie is present, then there is no risk of CSRF.
|
|
//nolint:govet
|
|
sessCookie, err := r.Cookie(codersdk.SessionTokenCookie)
|
|
if xerrors.Is(err, http.ErrNoCookie) {
|
|
return true
|
|
}
|
|
|
|
if token := r.Header.Get(codersdk.SessionTokenHeader); token == sessCookie.Value {
|
|
// If the cookie and header match, we can assume this is the same as just using the
|
|
// custom header auth. Custom header auth can bypass CSRF, as CSRF attacks
|
|
// cannot add custom headers.
|
|
return true
|
|
}
|
|
|
|
if token := r.URL.Query().Get(codersdk.SessionTokenCookie); token == sessCookie.Value {
|
|
// If the auth is set in a url param and matches the cookie, it
|
|
// is the same as just using the url param.
|
|
return true
|
|
}
|
|
|
|
// If the X-CSRF-TOKEN header is set, we can exempt the func if it's valid.
|
|
// This is the CSRF check.
|
|
sent := r.Header.Get("X-CSRF-TOKEN")
|
|
if sent != "" {
|
|
return nosurf.VerifyToken(nosurf.Token(r), sent)
|
|
}
|
|
return false
|
|
})
|
|
return mw
|
|
}
|
|
}
|