From 427ed6c98aa6c24606166eb45306866bc679f912 Mon Sep 17 00:00:00 2001 From: James Elliott Date: Sun, 17 Mar 2024 19:01:06 +1100 Subject: [PATCH] fix(server): oidc flow failure due to corb (#6921) This fixes an issue where the CORP/CORB/COEP headers cause issues with OpenID Connect 1.0 dialog windows. We will reevaluate these headers at a future date. Signed-off-by: James Elliott --- docs/content/overview/security/measures.md | 58 +++++-------------- internal/handlers/handler_authz_test.go | 2 +- internal/server/handlers.go | 11 ++-- .../example/compose/nginx/portal/nginx.conf | 9 --- 4 files changed, 21 insertions(+), 59 deletions(-) diff --git a/docs/content/overview/security/measures.md b/docs/content/overview/security/measures.md index 2f4b3ddb48082..75df0ff6022f4 100644 --- a/docs/content/overview/security/measures.md +++ b/docs/content/overview/security/measures.md @@ -25,9 +25,10 @@ Authelia sets several [cookie attributes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#attributes) to help prevent cookie theft: -1. `HttpOnly` is set forbidding client-side code like javascript from access to the cookie. -2. `Secure` is set forbidding the browser from sending the cookie to sites which do not use the [HTTPS] scheme. -3. `SameSite` is by default set to `Lax` which prevents it being sent over cross-origin requests. +1. `HttpOnly` is set, forbidding client-side code like javascript from access to the cookie. +2. `Secure` is set, forbidding the browser from sending the cookie to sites which do not use the [HTTPS] scheme. +3. `SameSite` is set to `Lax`, which prevents it being sent over cross-origin requests. An option to adjust this value + exists but is not recommended. Read about these attributes in detail on the [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie). @@ -43,7 +44,7 @@ will prevent domains from serving over [HTTP] at all as long as the user has vis if the attacker poisons DNS they are unable to get modern browsers to connect to a compromised host unless they can also obtain the certificate. -Note that using [HSTS] has consequences and you should do adequate research into understanding [HSTS] before you enable +Note that using [HSTS] has consequences, and you should do adequate research into understanding [HSTS] before you enable it. For example the [nginx blog] has a good article helping users understand it. ## Protection against username enumeration @@ -77,7 +78,7 @@ which is seeded every time it's used by a cryptographically secure 1024bit prime attacker obtains the file, each password has to be brute forced individually. Lastly Authelia's implementation of Argon2id is highly tunable. You can tune the key length, salt used, iterations -(time), parallelism, and memory usage. To read more about this please read how to +(time), parallelism, and memory usage. To read more about this, please read how to [configure](../../configuration/first-factor/file.md) file authentication. ## Protections against return oriented programming attacks and general hardening @@ -85,8 +86,8 @@ Lastly Authelia's implementation of Argon2id is highly tunable. You can tune the Authelia is built as a position independent executable which makes Return Oriented Programming (ROP) attacks significantly more difficult to execute reliably. -In addition it is built as a static binary with full relocation read-only support making this and several other -traditional binary weaknesses significantly more difficult to exploit. +In addition, it is built as a dynamically linked binary with full relocation read-only support, making this and several +other traditional binary weaknesses significantly more difficult to exploit. ## User profile and group membership always kept up-to-date (LDAP authentication provider) @@ -99,8 +100,9 @@ applications secured by Authelia. Additionally, it will invalidate any session where the user could not be retrieved from LDAP based on the user filter, for example if they were deleted or disabled provided the user filter is set correctly. These updates occur when a user accesses a resource protected by Authelia. This means you should ensure disabled users or users with expired passwords -are not obtainable using the LDAP filter, the default filter for Active Directory implements this behaviour. -LDAP implementations vary, so please ask if you need some assistance in configuring this. +are not obtainable using the LDAP filter, the default filter for Active Directory and several other implementation +defaults implement this behavior. LDAP implementations vary, so please ask if you need some assistance in configuring +this. These protections can be [tuned](../../configuration/first-factor/ldap.md#refresh-interval) according to your security policy by changing refresh_interval, however we believe that 5 minutes is a fairly safe interval. @@ -268,7 +270,7 @@ This is used to encrypt the session data when it is stored in the [Redis](../../ database. The value of this option should be long and as random as possible. See more in the [documentation](../../configuration/session/introduction.md#secret) for this option. -The validity period of session is highly configurable. For example in a highly security conscious domain you could +The validity period of session is highly configurable. For example, in a highly security conscious domain you could set the session [remember_me](../../configuration/session/introduction.md#remember_me) to 0 to disable this feature, and set the [expiration](../../configuration/session/introduction.md#expiration) to 2 hours and the [inactivity](../../configuration/session/introduction.md#inactivity) of 10 minutes. Configuring the session security in this @@ -281,7 +283,7 @@ This document previously detailed additional per-proxy configuration options tha improve security. These headers are now documented here and implemented by default in all responses due to the fact the experience should be the same regardless of which proxy you're utilizing and the area is rapidly evolving. -Users who need custom behaviours in this area can submit a request or remove/replace the headers as necessary. These +Users who need custom behaviors in this area can submit a request or remove/replace the headers as necessary. These headers will evolve over time just as the web standards and security recommendations evolve. These headers prevent loading Authelia in specific scenarios, primarily in an [Inline Frame](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe) which is generally considered a high @@ -289,7 +291,7 @@ security risk. The [OWASP](https://owasp.org/) helpful [HTTP Security Response Headers Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html) -was used as a basis for most of the decisions regarding these headers. Users who which to customize the behaviour should +was used as a basis for most of the decisions regarding these headers. Users who which to customize the behavior should consider this cheat sheet mandatory reading before they do so. #### X-XSS-Protection @@ -299,7 +301,7 @@ __Endpoints:__ All __Status:__ Unsupported Non-standard We do not include this header as this feature is not present in any modern browser and could introduce vulnerabilities -if enabled at all. Going forward [CORS], [CORP], CORB, and [COEP] are the standards for browser centric site security. +if enabled at all. Going forward [CORS], [CORP], CORB, and [COEP] are the standards for browser-centric site security. See the [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection) for more information. #### X-Content-Type-Options @@ -352,36 +354,6 @@ __Status:__ Non-standard Prevents browsers from performing a DNS prefetch for links displayed on Authelia pages. Not all browsers support this. See the [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-DNS-Prefetch-Control) for more information. - -#### Cross-Origin-Opener-Policy - -__Value:__ `same-origin` -__Endpoints:__ All -__Status:__ Supported Standard - -Enables context isolation for the Authelia page so only pages with the same origin are using the same browsing context. -See the [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy) for more -information. - -#### Cross-Origin-Embedder-Policy - -__Value:__ `require-corp` -__Endpoints:__ All -__Status:__ Supported Standard - -Prevents embedding of resources that do not have the [Cross-Origin-Resource-Policy](#cross-origin-resource-policy) -header. See the [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy) for more -information. - -#### Cross-Origin-Resource-Policy - -__Value:__ `same-site` -__Endpoints:__ All -__Status:__ Supported Standard - -Prevents inclusion of resources that do not share the same origin. See the -[MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy) for more information. - #### Pragma __Value:__ `no-cache` diff --git a/internal/handlers/handler_authz_test.go b/internal/handlers/handler_authz_test.go index 41e381a61b99f..d8c34cf18ff68 100644 --- a/internal/handlers/handler_authz_test.go +++ b/internal/handlers/handler_authz_test.go @@ -80,7 +80,7 @@ func (s *AuthzSuite) Builder() (builder *AuthzBuilder) { return } -func (s *AuthzSuite) BuilderWithBearerScheme() (buildier *AuthzBuilder) { +func (s *AuthzSuite) BuilderWithBearerScheme() (builder *AuthzBuilder) { switch s.implementation { case AuthzImplExtAuthz: return NewAuthzBuilder().WithImplementationExtAuthz().WithStrategies(NewHeaderProxyAuthorizationAuthnStrategy(model.AuthorizationSchemeBasic.String(), model.AuthorizationSchemeBearer.String()), NewCookieSessionAuthnStrategy(schema.NewRefreshIntervalDurationAlways())) diff --git a/internal/server/handlers.go b/internal/server/handlers.go index 1bb1eac35f7e6..113ab5dccf63d 100644 --- a/internal/server/handlers.go +++ b/internal/server/handlers.go @@ -125,8 +125,7 @@ func handleRouter(config *schema.Configuration, providers middlewares.Providers) handlerPublicHTML := newPublicHTMLEmbeddedHandler() handlerLocales := newLocalesEmbeddedHandler() - bridge := middlewares.NewBridgeBuilder(*config, providers). - WithPreMiddlewares(middlewares.SecurityHeaders).Build() + bridge := middlewares.NewBridgeBuilder(*config, providers).Build() bridgeSwagger := middlewares.NewBridgeBuilder(*config, providers). WithPreMiddlewares(middlewares.SecurityHeadersRelaxed).Build() @@ -182,16 +181,16 @@ func handleRouter(config *schema.Configuration, providers middlewares.Providers) } middlewareAPI := middlewares.NewBridgeBuilder(*config, providers). - WithPreMiddlewares(middlewares.SecurityHeaders, middlewares.SecurityHeadersNoStore, middlewares.SecurityHeadersCSPNone). + WithPreMiddlewares(middlewares.SecurityHeadersNoStore, middlewares.SecurityHeadersCSPNone). Build() middleware1FA := middlewares.NewBridgeBuilder(*config, providers). - WithPreMiddlewares(middlewares.SecurityHeaders, middlewares.SecurityHeadersNoStore, middlewares.SecurityHeadersCSPNone). + WithPreMiddlewares(middlewares.SecurityHeadersNoStore, middlewares.SecurityHeadersCSPNone). WithPostMiddlewares(middlewares.Require1FA). Build() middlewareElevated1FA := middlewares.NewBridgeBuilder(*config, providers). - WithPreMiddlewares(middlewares.SecurityHeaders, middlewares.SecurityHeadersNoStore, middlewares.SecurityHeadersCSPNone). + WithPreMiddlewares(middlewares.SecurityHeadersNoStore, middlewares.SecurityHeadersCSPNone). WithPostMiddlewares(middlewares.RequireElevated). Build() @@ -336,7 +335,7 @@ func handleRouter(config *schema.Configuration, providers middlewares.Providers) if providers.OpenIDConnect != nil { bridgeOIDC := middlewares.NewBridgeBuilder(*config, providers).WithPreMiddlewares( - middlewares.SecurityHeaders, middlewares.SecurityHeadersCSPNoneOpenIDConnect, middlewares.SecurityHeadersNoStore, + middlewares.SecurityHeadersCSPNoneOpenIDConnect, middlewares.SecurityHeadersNoStore, ).Build() r.GET("/api/oidc/consent", bridgeOIDC(handlers.OpenIDConnectConsentGET)) diff --git a/internal/suites/example/compose/nginx/portal/nginx.conf b/internal/suites/example/compose/nginx/portal/nginx.conf index 22efd7e8c911d..6d3da4c480a8b 100644 --- a/internal/suites/example/compose/nginx/portal/nginx.conf +++ b/internal/suites/example/compose/nginx/portal/nginx.conf @@ -115,9 +115,6 @@ http { add_header X-Frame-Options "DENY"; add_header Permissions-Policy "accelerometer=(), autoplay=(), camera=(), display-capture=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), screen-wake-lock=(), sync-xhr=(), xr-spatial-tracking=(), interest-cohort=()"; add_header X-DNS-Prefetch-Control "off"; - add_header Cross-Origin-Opener-Policy "same-origin"; - add_header Cross-Origin-Embedder-Policy "require-corp"; - add_header Cross-Origin-Resource-Policy "same-origin"; proxy_pass $frontend_endpoint; } @@ -168,9 +165,6 @@ http { add_header X-Frame-Options "DENY"; add_header Permissions-Policy "accelerometer=(), autoplay=(), camera=(), display-capture=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), screen-wake-lock=(), sync-xhr=(), xr-spatial-tracking=(), interest-cohort=()"; add_header X-DNS-Prefetch-Control "off"; - add_header Cross-Origin-Opener-Policy "same-origin"; - add_header Cross-Origin-Embedder-Policy "require-corp"; - add_header Cross-Origin-Resource-Policy "same-origin"; error_page 497 301 =307 https://$host:$server_port$request_uri; @@ -342,9 +336,6 @@ http { add_header X-Frame-Options "DENY"; add_header Permissions-Policy "accelerometer=(), autoplay=(), camera=(), display-capture=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), screen-wake-lock=(), sync-xhr=(), xr-spatial-tracking=(), interest-cohort=()"; add_header X-DNS-Prefetch-Control "off"; - add_header Cross-Origin-Opener-Policy "same-origin"; - add_header Cross-Origin-Embedder-Policy "require-corp"; - add_header Cross-Origin-Resource-Policy "same-origin"; error_page 497 301 =307 https://$host:$server_port$request_uri;