From e408cb19b175624fa9955acbebecb1abb84287d4 Mon Sep 17 00:00:00 2001 From: James Elliott Date: Thu, 2 Feb 2023 18:13:18 +1100 Subject: [PATCH] test: adjust tests and docs to be similar (#4856) --- docs/content/en/integration/proxies/caddy.md | 8 +- docs/content/en/integration/proxies/envoy.md | 3 +- .../content/en/integration/proxies/haproxy.md | 56 ++++- docs/content/en/integration/proxies/nginx.md | 18 +- .../content/en/integration/proxies/traefik.md | 4 +- .../en/integration/proxies/traefikv1.md | 4 +- .../suites/example/compose/envoy/envoy.yaml | 6 +- .../example/compose/haproxy/haproxy.cfg | 13 ++ .../compose/httpbin/docker-compose.yml | 2 +- .../compose/nginx/backend/docker-compose.yml | 2 +- .../example/compose/nginx/portal/nginx.conf | 198 ++++++++++++------ .../compose/traefik2/docker-compose.yml | 2 +- 12 files changed, 235 insertions(+), 81 deletions(-) diff --git a/docs/content/en/integration/proxies/caddy.md b/docs/content/en/integration/proxies/caddy.md index 1f2243883..1a8f00d7a 100644 --- a/docs/content/en/integration/proxies/caddy.md +++ b/docs/content/en/integration/proxies/caddy.md @@ -102,7 +102,7 @@ nextcloud.example.com { ## The following commented line is for configuring the Authelia URL in the proxy. We strongly suggest ## this is configured in the Session Cookies section of the Authelia configuration. # uri /api/authz/forward-auth?authelia_url=https://auth.example.com/ - copy_headers Remote-User Remote-Groups Remote-Name Remote-Email + copy_headers Authorization Proxy-Authorization Remote-User Remote-Groups Remote-Email Remote-Name ## This import needs to be included if you're relying on a trusted proxies configuration. import trusted_proxy_list @@ -141,7 +141,7 @@ example.com { handle @nextcloud { forward_auth authelia:9091 { uri /api/authz/forward-auth?authelia_url=https://example.com/authelia/ - copy_headers Remote-User Remote-Groups Remote-Name Remote-Email + copy_headers Authorization Proxy-Authorization Remote-User Remote-Groups Remote-Email Remote-Name ## This import needs to be included if you're relying on a trusted proxies configuration. import trusted_proxy_list @@ -198,10 +198,12 @@ nextcloud.example.com { ## 2. Copy the relevant headers from the auth request and provide them to the backend. @good status 2xx handle_response @good { + request_header Authorization {http.reverse_proxy.header.Authorization} + request_header Proxy-Authorization {http.reverse_proxy.header.Proxy-Authorization} request_header Remote-User {http.reverse_proxy.header.Remote-User} request_header Remote-Groups {http.reverse_proxy.header.Remote-Groups} - request_header Remote-Name {http.reverse_proxy.header.Remote-Name} request_header Remote-Email {http.reverse_proxy.header.Remote-Email} + request_header Remote-Name {http.reverse_proxy.header.Remote-Name} } } diff --git a/docs/content/en/integration/proxies/envoy.md b/docs/content/en/integration/proxies/envoy.md index 25cece96d..edb2a1eb3 100644 --- a/docs/content/en/integration/proxies/envoy.md +++ b/docs/content/en/integration/proxies/envoy.md @@ -177,9 +177,10 @@ static_resources: authorization_request: allowed_headers: patterns: + - exact: authorization + - exact: proxy-authorization - exact: accept - exact: cookie - - exact: proxy-authorization headers_to_add: - key: X-Forwarded-Proto value: '%REQ(:SCHEME)%' diff --git a/docs/content/en/integration/proxies/haproxy.md b/docs/content/en/integration/proxies/haproxy.md index e8168068b..353ebb9db 100644 --- a/docs/content/en/integration/proxies/haproxy.md +++ b/docs/content/en/integration/proxies/haproxy.md @@ -218,29 +218,53 @@ backend be_authelia server authelia authelia:9091 backend be_nextcloud - # Pass Remote-User, Remote-Name, Remote-Email and Remote-Groups headers + ## Pass the special authorization response headers to the protected application. + acl authorization_exist var(req.auth_response_header.authorization) -m found + acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found + + http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist + http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist + + ## Pass the special metadata response headers to the protected application. acl remote_user_exist var(req.auth_response_header.remote_user) -m found acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found acl remote_name_exist var(req.auth_response_header.remote_name) -m found acl remote_email_exist var(req.auth_response_header.remote_email) -m found + http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist + ## Pass the Set-Cookie response headers to the user. + acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found + http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist + server nextcloud nextcloud:443 ssl verify none backend be_heimdall - # Pass Remote-User, Remote-Name, Remote-Email and Remote-Groups headers + ## Pass the special authorization response headers to the protected application. + acl authorization_exist var(req.auth_response_header.authorization) -m found + acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found + + http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist + http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist + + ## Pass the special metadata response headers to the protected application. acl remote_user_exist var(req.auth_response_header.remote_user) -m found acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found acl remote_name_exist var(req.auth_response_header.remote_name) -m found acl remote_email_exist var(req.auth_response_header.remote_email) -m found + http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist + ## Pass the Set-Cookie response headers to the user. + acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found + http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist + server heimdall heimdall:443 ssl verify none ``` @@ -325,29 +349,53 @@ listen authelia_proxy server authelia authelia:9091 ssl verify none backend be_nextcloud - # Pass Remote-User, Remote-Name, Remote-Email and Remote-Groups headers + ## Pass the special authorization response headers to the protected application. + acl authorization_exist var(req.auth_response_header.authorization) -m found + acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found + + http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist + http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist + + ## Pass the special metadata response headers to the protected application. acl remote_user_exist var(req.auth_response_header.remote_user) -m found acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found acl remote_name_exist var(req.auth_response_header.remote_name) -m found acl remote_email_exist var(req.auth_response_header.remote_email) -m found + http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist + ## Pass the Set-Cookie response headers to the user. + acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found + http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist + server nextcloud nextcloud:443 ssl verify none backend be_heimdall - # Pass Remote-User, Remote-Name, Remote-Email and Remote-Groups headers + ## Pass the special authorization response headers to the protected application. + acl authorization_exist var(req.auth_response_header.authorization) -m found + acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found + + http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist + http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist + + ## Pass the special metadata response headers to the protected application. acl remote_user_exist var(req.auth_response_header.remote_user) -m found acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found acl remote_name_exist var(req.auth_response_header.remote_name) -m found acl remote_email_exist var(req.auth_response_header.remote_email) -m found + http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist + ## Pass the Set-Cookie response headers to the user. + acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found + http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist + server heimdall heimdall:443 ssl verify none ``` diff --git a/docs/content/en/integration/proxies/nginx.md b/docs/content/en/integration/proxies/nginx.md index 7f4907b16..373834264 100644 --- a/docs/content/en/integration/proxies/nginx.md +++ b/docs/content/en/integration/proxies/nginx.md @@ -433,17 +433,29 @@ set_escape_uri $target_url $scheme://$http_host$request_uri; ## Uncomment this line if you're using NGINX without the http_set_misc module. # set $target_url $scheme://$http_host$request_uri; -## Save the upstream response headers from Authelia to variables. +## Save the upstream authorization response headers from Authelia to variables. +auth_request_set $authorization $upstream_http_authorization; +auth_request_set $proxy_authorization $upstream_http_proxy_authorization; + +## Inject the authorization response headers from the variables into the request made to the backend. +proxy_set_header Authorization $authorization; +proxy_set_header Proxy-Authorization $proxy_authorization; + +## Save the upstream metadata response headers from Authelia to variables. auth_request_set $user $upstream_http_remote_user; auth_request_set $groups $upstream_http_remote_groups; auth_request_set $name $upstream_http_remote_name; auth_request_set $email $upstream_http_remote_email; -## Inject the response headers from the variables into the request made to the backend. +## Inject the metadata response headers from the variables into the request made to the backend. proxy_set_header Remote-User $user; proxy_set_header Remote-Groups $groups; -proxy_set_header Remote-Name $name; proxy_set_header Remote-Email $email; +proxy_set_header Remote-Name $name; + +## Include the Set-Cookie header if present. +auth_request_set $cookie $upstream_http_set_cookie; +add_header Set-Cookie $cookie; ## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal. error_page 401 =302 https://auth.example.com/?rd=$target_url; diff --git a/docs/content/en/integration/proxies/traefik.md b/docs/content/en/integration/proxies/traefik.md index 0a93fe046..0d1ce5303 100644 --- a/docs/content/en/integration/proxies/traefik.md +++ b/docs/content/en/integration/proxies/traefik.md @@ -157,7 +157,7 @@ services: ## configured in the Session Cookies section of the Authelia configuration. # - 'traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F' - 'traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true' - - 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Name,Remote-Email' + - 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name' nextcloud: container_name: nextcloud image: linuxserver/nextcloud @@ -503,7 +503,7 @@ This can be avoided a couple different ways: ## configured in the Session Cookies section of the Authelia configuration. # - 'traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F' - 'traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true' -- 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Name,Remote-Email' +- 'traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name' ``` ## See Also diff --git a/docs/content/en/integration/proxies/traefikv1.md b/docs/content/en/integration/proxies/traefikv1.md index d63dc7414..7f0e0f598 100644 --- a/docs/content/en/integration/proxies/traefikv1.md +++ b/docs/content/en/integration/proxies/traefikv1.md @@ -137,7 +137,7 @@ services: ## configured in the Session Cookies section of the Authelia configuration. # - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/authz/forward-auth?authelia_url=https%3A%2F%2Fauth.example.com%2F' - 'traefik.frontend.auth.forward.trustForwardHeader=true' - - 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Name,Remote-Email' + - 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name' expose: - 443 restart: unless-stopped @@ -156,7 +156,7 @@ services: - 'traefik.frontend.rule=Host:heimdall.example.com' - 'traefik.frontend.auth.forward.address=http://authelia:9091/api/authz/forward-auth/basic' - 'traefik.frontend.auth.forward.trustForwardHeader=true' - - 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Name,Remote-Email' + - 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name' expose: - 443 restart: unless-stopped diff --git a/internal/suites/example/compose/envoy/envoy.yaml b/internal/suites/example/compose/envoy/envoy.yaml index f43d28649..77783ebe4 100644 --- a/internal/suites/example/compose/envoy/envoy.yaml +++ b/internal/suites/example/compose/envoy/envoy.yaml @@ -87,16 +87,20 @@ static_resources: authorization_request: allowed_headers: patterns: + - exact: authorization + - exact: proxy-authorization - exact: accept - exact: cookie - - exact: proxy-authorization headers_to_add: - key: X-Forwarded-Proto value: '%REQ(:SCHEME)%' authorization_response: allowed_upstream_headers: patterns: + - exact: authorization + - exact: proxy-authorization - prefix: remote- + - prefix: authelia- allowed_client_headers: patterns: - exact: set-cookie diff --git a/internal/suites/example/compose/haproxy/haproxy.cfg b/internal/suites/example/compose/haproxy/haproxy.cfg index 68e16148a..529920b8a 100644 --- a/internal/suites/example/compose/haproxy/haproxy.cfg +++ b/internal/suites/example/compose/haproxy/haproxy.cfg @@ -82,15 +82,28 @@ backend fe_authelia server authelia-backend authelia-backend:9091 check backup resolvers docker ssl verify none backend be_httpbin + ## Pass the special authorization response headers to the protected application. + acl authorization_exist var(req.auth_response_header.authorization) -m found + acl proxy_authorization_exist var(req.auth_response_header.proxy_authorization) -m found + + http-request set-header Authorization %[var(req.auth_response_header.authorization)] if authorization_exist + http-request set-header Proxy-Authorization %[var(req.auth_response_header.proxy_authorization)] if proxy_authorization_exist + + ## Pass the special metadata response headers to the protected application. acl remote_user_exist var(req.auth_response_header.remote_user) -m found acl remote_groups_exist var(req.auth_response_header.remote_groups) -m found acl remote_name_exist var(req.auth_response_header.remote_name) -m found acl remote_email_exist var(req.auth_response_header.remote_email) -m found + http-request set-header Remote-User %[var(req.auth_response_header.remote_user)] if remote_user_exist http-request set-header Remote-Groups %[var(req.auth_response_header.remote_groups)] if remote_groups_exist http-request set-header Remote-Name %[var(req.auth_response_header.remote_name)] if remote_name_exist http-request set-header Remote-Email %[var(req.auth_response_header.remote_email)] if remote_email_exist + ## Pass the Set-Cookie response headers to the user. + acl set_cookie_exist var(req.auth_response_header.set_cookie) -m found + http-response set-header Set-Cookie %[var(req.auth_response_header.set_cookie)] if set_cookie_exist + server httpbin-backend httpbin:8000 resolvers docker backend be_mail diff --git a/internal/suites/example/compose/httpbin/docker-compose.yml b/internal/suites/example/compose/httpbin/docker-compose.yml index 15683d340..f1dffa0d4 100644 --- a/internal/suites/example/compose/httpbin/docker-compose.yml +++ b/internal/suites/example/compose/httpbin/docker-compose.yml @@ -12,7 +12,7 @@ services: - 'traefik.frontend.auth.forward.address=https://authelia-backend:9091/api/authz/forward-auth' - 'traefik.frontend.auth.forward.tls.insecureSkipVerify=true' - 'traefik.frontend.auth.forward.trustForwardHeader=true' - - 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' + - 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name' # Traefik 2.x - 'traefik.enable=true' - 'traefik.http.routers.httpbin.rule=Host(`public.example.com`) && Path(`/headers`)' diff --git a/internal/suites/example/compose/nginx/backend/docker-compose.yml b/internal/suites/example/compose/nginx/backend/docker-compose.yml index e71ed8dbd..b6abe101b 100644 --- a/internal/suites/example/compose/nginx/backend/docker-compose.yml +++ b/internal/suites/example/compose/nginx/backend/docker-compose.yml @@ -9,7 +9,7 @@ services: - 'traefik.frontend.auth.forward.address=https://authelia-backend:9091/api/authz/forward-auth' # yamllint disable-line rule:line-length - 'traefik.frontend.auth.forward.tls.insecureSkipVerify=true' - 'traefik.frontend.auth.forward.trustForwardHeader=true' - - 'traefik.frontend.auth.forward.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email' + - 'traefik.frontend.auth.forward.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name' # Traefik 2.x - 'traefik.enable=true' - 'traefik.http.routers.protectedapps.rule=Host(`home.example.com`,`public.example.com`,`secure.example.com`,`admin.example.com`,`singlefactor.example.com`)' # yamllint disable-line rule:line-length diff --git a/internal/suites/example/compose/nginx/portal/nginx.conf b/internal/suites/example/compose/nginx/portal/nginx.conf index 0af06dfa4..e0abc65d3 100644 --- a/internal/suites/example/compose/nginx/portal/nginx.conf +++ b/internal/suites/example/compose/nginx/portal/nginx.conf @@ -148,7 +148,7 @@ http { server_name ~^(public|admin|secure|dev|singlefactor|mx[1-2])(\.mail)?\.(?example([0-9])*\.com)$; resolver 127.0.0.11 ipv6=off; - set $upstream_verify https://authelia-backend:9091/api/authz/auth-request; + set $upstream_authelia https://authelia-backend:9091/api/authz/auth-request; set $upstream_endpoint http://nginx-backend; set $upstream_headers http://httpbin:8000/headers; @@ -163,22 +163,38 @@ http { # Reverse proxy to the backend. It is protected by Authelia by forwarding authorization checks # to the virtual endpoint introduced by nginx and declared in the next block. location / { - auth_request /auth_verify; + ## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource. + auth_request /authelia; - auth_request_set $user $upstream_http_remote_user; - proxy_set_header Remote-User $user; + ## Set the $target_url variable based on the original request. + set $target_url $scheme://$http_host$request_uri; - auth_request_set $groups $upstream_http_remote_groups; - proxy_set_header Remote-Groups $groups; + ## Save the upstream authorization response headers from Authelia to variables. + auth_request_set $authorization $upstream_http_authorization; + auth_request_set $proxy_authorization $upstream_http_proxy_authorization; - auth_request_set $name $upstream_http_remote_name; - proxy_set_header Remote-Name $name; + ## Inject the authorization response headers from the variables into the request made to the backend. + proxy_set_header Authorization $authorization; + proxy_set_header Proxy-Authorization $proxy_authorization; - auth_request_set $email $upstream_http_remote_email; - proxy_set_header Remote-Email $email; + ## Save the upstream metadata response headers from Authelia to variables. + auth_request_set $user $upstream_http_remote_user; + auth_request_set $groups $upstream_http_remote_groups; + auth_request_set $name $upstream_http_remote_name; + auth_request_set $email $upstream_http_remote_email; - # Route the request to the correct virtual host in the backend. - proxy_set_header Host $http_host; + ## Inject the metadata response headers from the variables into the request made to the backend. + proxy_set_header Remote-User $user; + proxy_set_header Remote-Groups $groups; + proxy_set_header Remote-Email $email; + proxy_set_header Remote-Name $name; + + ## Include the Set-Cookie header if present. + auth_request_set $cookie $upstream_http_set_cookie; + add_header Set-Cookie $cookie; + + ## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal. + error_page 401 =302 https://login.$basedomain:8080/?rd=$target_url; # Authelia relies on Proxy-Authorization header to authenticate in basic auth. # but for the sake of simplicity (because Authorization in supported in most @@ -186,22 +202,17 @@ http { # Proxy-Authorization before sending it to Authelia. proxy_set_header Proxy-Authorization $http_authorization; - # mitigate HTTPoxy Vulnerability - # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ - proxy_set_header Proxy ""; - - # Set the `target_url` variable based on the request. It will be used to build the portal - # URL with the correct redirection parameter. - set $target_url $scheme://$http_host$request_uri; - error_page 401 =302 https://login.$basedomain:8080/?rd=$target_url; + # Route the request to the correct virtual host in the backend. + proxy_set_header Host $http_host; proxy_pass $upstream_endpoint; } # Virtual endpoint forwarding requests to Authelia server. - location /auth_verify { - internal; - proxy_set_header X-Real-IP $remote_addr; + location /authelia { + ## Essential Proxy Configuration + internal; + proxy_pass $upstream_authelia; # Provide either X-Original-URL and X-Forwarded-Proto or # X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-URI or both. @@ -209,39 +220,67 @@ http { # # X-Forwarded-Proto is mandatory since Authelia uses the "trust proxy" option. # See https://expressjs.com/en/guide/behind-proxies.html - proxy_set_header X-Original-Method $request_method; - proxy_set_header X-Original-URL $scheme://$http_host$request_uri; - - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Original-Method $request_method; + proxy_set_header X-Original-URL $scheme://$http_host$request_uri; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Content-Length ""; + proxy_set_header Connection ""; # Authelia can receive Proxy-Authorization to authenticate however most of the clients # support Authorization instead. Therefore we rewrite Authorization into Proxy-Authorization. proxy_set_header Proxy-Authorization $http_authorization; - proxy_pass_request_body off; - proxy_set_header Content-Length ""; + ## Basic Proxy Configuration + proxy_pass_request_body off; + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead + proxy_redirect http:// $scheme://; + proxy_http_version 1.1; + proxy_cache_bypass $cookie_session; + proxy_no_cache $cookie_session; + proxy_buffers 4 32k; + client_body_buffer_size 128k; - proxy_pass $upstream_verify; + ## Advanced Proxy Configuration + send_timeout 5m; + proxy_read_timeout 240; + proxy_send_timeout 240; + proxy_connect_timeout 240; } # Used by suites to test the forwarded users and groups headers produced by Authelia. location /headers { - auth_request /auth_verify; + ## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource. + auth_request /authelia; - auth_request_set $user $upstream_http_remote_user; - proxy_set_header Remote-User $user; + ## Set the $target_url variable based on the original request. + set $target_url $scheme://$http_host$request_uri; - auth_request_set $groups $upstream_http_remote_groups; - proxy_set_header Remote-Groups $groups; + ## Save the upstream authorization response headers from Authelia to variables. + auth_request_set $authorization $upstream_http_authorization; + auth_request_set $proxy_authorization $upstream_http_proxy_authorization; - auth_request_set $name $upstream_http_remote_name; - proxy_set_header Remote-Name $name; + ## Inject the authorization response headers from the variables into the request made to the backend. + proxy_set_header Authorization $authorization; + proxy_set_header Proxy-Authorization $proxy_authorization; - auth_request_set $email $upstream_http_remote_email; - proxy_set_header Remote-Email $email; + ## Save the upstream metadata response headers from Authelia to variables. + auth_request_set $user $upstream_http_remote_user; + auth_request_set $groups $upstream_http_remote_groups; + auth_request_set $name $upstream_http_remote_name; + auth_request_set $email $upstream_http_remote_email; - set $target_url $scheme://$http_host$request_uri; - error_page 401 =302 https://login.$basedomain:8080/?rd=$target_url; + ## Inject the metadata response headers from the variables into the request made to the backend. + proxy_set_header Remote-User $user; + proxy_set_header Remote-Groups $groups; + proxy_set_header Remote-Email $email; + proxy_set_header Remote-Name $name; + + ## Include the Set-Cookie header if present. + auth_request_set $cookie $upstream_http_set_cookie; + add_header Set-Cookie $cookie; + + ## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal. + error_page 401 =302 https://login.$basedomain:8080/?rd=$target_url; proxy_pass $upstream_headers; } @@ -253,7 +292,7 @@ http { server_name ~^oidc(-public)?\.(?example([0-9])*\.com)$; resolver 127.0.0.11 ipv6=off; - set $upstream_verify https://authelia-backend:9091/api/authz/auth-request; + set $upstream_authelia https://authelia-backend:9091/api/authz/auth-request; set $upstream_endpoint http://oidc-client:8080; ssl_certificate /etc/ssl/server.cert; @@ -267,27 +306,50 @@ http { # Reverse proxy to the backend. It is protected by Authelia by forwarding authorization checks # to the virtual endpoint introduced by nginx and declared in the next block. location / { - auth_request /auth_verify; + ## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource. + auth_request /authelia; + + ## Set the $target_url variable based on the original request. + set $target_url $scheme://$http_host$request_uri; + + ## Save the upstream authorization response headers from Authelia to variables. + auth_request_set $authorization $upstream_http_authorization; + auth_request_set $proxy_authorization $upstream_http_proxy_authorization; + + ## Inject the authorization response headers from the variables into the request made to the backend. + proxy_set_header Authorization $authorization; + proxy_set_header Proxy-Authorization $proxy_authorization; + + ## Save the upstream metadata response headers from Authelia to variables. + auth_request_set $user $upstream_http_remote_user; + auth_request_set $groups $upstream_http_remote_groups; + auth_request_set $name $upstream_http_remote_name; + auth_request_set $email $upstream_http_remote_email; + + ## Inject the metadata response headers from the variables into the request made to the backend. + proxy_set_header Remote-User $user; + proxy_set_header Remote-Groups $groups; + proxy_set_header Remote-Email $email; + proxy_set_header Remote-Name $name; + + ## Include the Set-Cookie header if present. + auth_request_set $cookie $upstream_http_set_cookie; + add_header Set-Cookie $cookie; + + ## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal. + error_page 401 =302 https://login.$basedomain:8080/?rd=$target_url; # Route the request to the correct virtual host in the backend. proxy_set_header Host $http_host; - # mitigate HTTPoxy Vulnerability - # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ - proxy_set_header Proxy ""; - - # Set the `target_url` variable based on the request. It will be used to build the portal - # URL with the correct redirection parameter. - set $target_url $scheme://$http_host$request_uri; - error_page 401 =302 https://login.$basedomain:8080/?rd=$target_url; - proxy_pass $upstream_endpoint; } # Virtual endpoint forwarding requests to Authelia server. - location /auth_verify { - internal; - proxy_set_header X-Real-IP $remote_addr; + location /authelia { + ## Essential Proxy Configuration + internal; + proxy_pass $upstream_authelia; # Provide either X-Original-URL and X-Forwarded-Proto or # X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-URI or both. @@ -295,19 +357,31 @@ http { # # X-Forwarded-Proto is mandatory since Authelia uses the "trust proxy" option. # See https://expressjs.com/en/guide/behind-proxies.html - proxy_set_header X-Original-Method $request_method; - proxy_set_header X-Original-URL $scheme://$http_host$request_uri; - - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Original-Method $request_method; + proxy_set_header X-Original-URL $scheme://$http_host$request_uri; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Content-Length ""; + proxy_set_header Connection ""; # Authelia can receive Proxy-Authorization to authenticate however most of the clients # support Authorization instead. Therefore we rewrite Authorization into Proxy-Authorization. proxy_set_header Proxy-Authorization $http_authorization; - proxy_pass_request_body off; - proxy_set_header Content-Length ""; + ## Basic Proxy Configuration + proxy_pass_request_body off; + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead + proxy_redirect http:// $scheme://; + proxy_http_version 1.1; + proxy_cache_bypass $cookie_session; + proxy_no_cache $cookie_session; + proxy_buffers 4 32k; + client_body_buffer_size 128k; - proxy_pass $upstream_verify; + ## Advanced Proxy Configuration + send_timeout 5m; + proxy_read_timeout 240; + proxy_send_timeout 240; + proxy_connect_timeout 240; } } diff --git a/internal/suites/example/compose/traefik2/docker-compose.yml b/internal/suites/example/compose/traefik2/docker-compose.yml index ea30cf683..04b198e7e 100644 --- a/internal/suites/example/compose/traefik2/docker-compose.yml +++ b/internal/suites/example/compose/traefik2/docker-compose.yml @@ -15,7 +15,7 @@ services: - 'traefik.http.middlewares.authelia.forwardauth.address=https://authelia-backend:9091${PathPrefix}/api/authz/forward-auth' # yamllint disable-line rule:line-length - 'traefik.http.middlewares.authelia.forwardauth.tls.insecureSkipVerify=true' - 'traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true' - - 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User, Remote-Groups, Remote-Name, Remote-Email' # yamllint disable-line rule:line-length + - 'traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Authorization,Proxy-Authorization,Remote-User,Remote-Groups,Remote-Email,Remote-Name' # yamllint disable-line rule:line-length command: - '--accesslog=true' - '--api'