From d31e566873ff85f86b1616166f564ea357ec45f1 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Sat, 14 Jan 2023 22:18:22 +0100 Subject: [PATCH] outposts/proxy: add header to prevent redirects Signed-off-by: Jens Langhammer --- internal/outpost/proxyv2/application/auth.go | 9 +++------ internal/outpost/proxyv2/application/utils.go | 11 +++++++++++ internal/outpost/proxyv2/constants/constants.go | 5 +++++ website/docs/providers/proxy/header_authentication.md | 6 ++++++ 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/internal/outpost/proxyv2/application/auth.go b/internal/outpost/proxyv2/application/auth.go index 617fd4985..66715eed4 100644 --- a/internal/outpost/proxyv2/application/auth.go +++ b/internal/outpost/proxyv2/application/auth.go @@ -8,9 +8,6 @@ import ( "goauthentik.io/internal/outpost/proxyv2/constants" ) -const HeaderAuthorization = "Authorization" -const AuthBearer = "Bearer " - // checkAuth Get claims which are currently in session // Returns an error if the session can't be loaded or the claims can't be parsed/type-cast func (a *Application) checkAuth(rw http.ResponseWriter, r *http.Request) (*Claims, error) { @@ -70,7 +67,7 @@ func (a *Application) getClaimsFromSession(r *http.Request) *Claims { } func (a *Application) getClaimsFromCache(r *http.Request) *Claims { - key := r.Header.Get(HeaderAuthorization) + key := r.Header.Get(constants.HeaderAuthorization) item := a.authHeaderCache.Get(key) if item != nil && !item.IsExpired() { v := item.Value() @@ -88,12 +85,12 @@ func (a *Application) saveAndCacheClaims(rw http.ResponseWriter, r *http.Request return nil, err } - key := r.Header.Get(HeaderAuthorization) + key := r.Header.Get(constants.HeaderAuthorization) item := a.authHeaderCache.Get(key) // Don't set when the key is already found if item == nil { a.authHeaderCache.Set(key, claims, time.Second*60) } - r.Header.Del(HeaderAuthorization) + r.Header.Del(constants.HeaderAuthorization) return &claims, nil } diff --git a/internal/outpost/proxyv2/application/utils.go b/internal/outpost/proxyv2/application/utils.go index b0c946284..30bf69b66 100644 --- a/internal/outpost/proxyv2/application/utils.go +++ b/internal/outpost/proxyv2/application/utils.go @@ -1,6 +1,7 @@ package application import ( + "fmt" "net/http" "net/url" "path" @@ -34,6 +35,16 @@ func (a *Application) redirectToStart(rw http.ResponseWriter, r *http.Request) { if err != nil { a.log.WithError(err).Warning("failed to decode session") } + if r.Header.Get(constants.HeaderNoRedirect) == "true" { + er := a.errorTemplates.Execute(rw, ErrorPageData{ + Title: "Unauthenticated", + Message: fmt.Sprintf("Due to '%s' being set, no redirect is performed.", constants.HeaderNoRedirect), + ProxyPrefix: "/outpost.goauthentik.io", + }) + if er != nil { + http.Error(rw, "Internal Server Error", http.StatusInternalServerError) + } + } redirectUrl := urlPathSet(a.proxyConfig.ExternalHost, r.URL.Path) diff --git a/internal/outpost/proxyv2/constants/constants.go b/internal/outpost/proxyv2/constants/constants.go index 366f5dc5b..e93fe8f76 100644 --- a/internal/outpost/proxyv2/constants/constants.go +++ b/internal/outpost/proxyv2/constants/constants.go @@ -6,3 +6,8 @@ const SessionOAuthState = "oauth_state" const SessionClaims = "claims" const SessionRedirect = "redirect" + +const HeaderAuthorization = "Authorization" +const HeaderNoRedirect = "X-Authentik-No-Redirect" + +const AuthBearer = "Bearer " diff --git a/website/docs/providers/proxy/header_authentication.md b/website/docs/providers/proxy/header_authentication.md index 67321924a..d774f6ca6 100644 --- a/website/docs/providers/proxy/header_authentication.md +++ b/website/docs/providers/proxy/header_authentication.md @@ -2,6 +2,8 @@ title: Header authentication --- +## Sending authentication + ### Send HTTP Basic authentication Proxy providers have the option to _Send HTTP-Basic Authentication_ to the upstream authentication. When the option in the provider is enabled, two attributes must be specified. These attributes are the keys of values which can be saved on a user or group level that contain the credentials. @@ -17,6 +19,10 @@ These credentials are only retrieved when the user authenticates to the proxy. If the user does not have a matching attribute, authentik falls back to using the user's email address as username, and the password will be empty if not found. +## Receiving authentication + +It is recommended to set the `X-Authentik-No-Redirect` header to `true` to prevent redirects when sending requests via the below methods. This prevents additional load when unauthenticated requests are retried and all get redirected to a flow executor. + ### Receiving HTTP Basic authentication :::info