From ee39467ade12aa6dc6b69b0a8db3f0615f75f126 Mon Sep 17 00:00:00 2001 From: Benjamin FERNANDEZ Date: Tue, 18 Jul 2023 14:58:24 +0200 Subject: [PATCH] Add frame ancestor configuration for web app to prevent clickjacking --- cmd/dex/config.go | 1 + cmd/dex/serve.go | 4 ++++ server/server.go | 26 ++++++++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/cmd/dex/config.go b/cmd/dex/config.go index 831156fd40..8cd539707d 100644 --- a/cmd/dex/config.go +++ b/cmd/dex/config.go @@ -150,6 +150,7 @@ type Web struct { TLSCert string `json:"tlsCert"` TLSKey string `json:"tlsKey"` AllowedOrigins []string `json:"allowedOrigins"` + FrameAncestors []string `json:"frameAncestors"` } // Telemetry is the config format for telemetry including the HTTP server config. diff --git a/cmd/dex/serve.go b/cmd/dex/serve.go index 47b090aeab..0de06a56e0 100644 --- a/cmd/dex/serve.go +++ b/cmd/dex/serve.go @@ -253,6 +253,10 @@ func runServe(options serveOptions) error { logger.Infof("config allowed origins: %s", c.Web.AllowedOrigins) } + if len(c.Web.FrameAncestors) > 0 { + logger.Infof("config allowed frame ancestors: %s", c.Web.FrameAncestors) + } + // explicitly convert to UTC. now := func() time.Time { return time.Now().UTC() } diff --git a/server/server.go b/server/server.go index 444fb7e15a..57b2d57c0f 100644 --- a/server/server.go +++ b/server/server.go @@ -77,6 +77,11 @@ type Config struct { // domain. AllowedOrigins []string + // List of domain allowed to frame the content of the application. + // By default no one is accepted to prevent against clickjacking. + // Passing in "*" will allow any domain + FrameAncestors []string + // If enabled, the server won't prompt the user to approve authorization requests. // Logging in implies approval. SkipApprovalScreen bool @@ -339,7 +344,28 @@ func newServer(ctx context.Context, c Config, rotationStrategy rotationStrategy) } } + + // frame-ancestors middleware + frameAncestorsMidldleware := func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var ancestors string + if len(c.FrameAncestors) > 0 { + for i := 0; i < len(c.FrameAncestors); i++ { + if c.FrameAncestors[i] == issuerURL.String() { + c.FrameAncestors[i] = "'self'" + } + } + ancestors = strings.Join(c.FrameAncestors, " ") + } else { + ancestors = "'none'" + } + w.Header().Set("Content-Security-Policy", "frame-ancestors "+ancestors) + next.ServeHTTP(w, r) + }) + } + r := mux.NewRouter().SkipClean(true).UseEncodedPath() + r.Use(frameAncestorsMidldleware) handle := func(p string, h http.Handler) { r.Handle(path.Join(issuerURL.Path, p), instrumentHandlerCounter(p, h)) }