providers/proxy: send token request internally, with overwritten host header (#4675)

* send token request internally, with overwritten host header

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L 2023-02-13 16:34:47 +01:00 committed by GitHub
parent 925477b3a2
commit ec42b597ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 55 additions and 20 deletions

View File

@ -43,6 +43,7 @@ def clean_expired_models(self: MonitoredTask):
amount = 0
for session in AuthenticatedSession.objects.all():
cache_key = f"{KEY_PREFIX}{session.session_key}"
value = None
try:
value = cache.get(cache_key)
# pylint: disable=broad-except

View File

@ -5,6 +5,7 @@ from django.test import TestCase
from authentik.core.models import User
from authentik.policies.dummy.models import DummyPolicy
from authentik.policies.engine import PolicyEngine
from authentik.policies.exceptions import PolicyEngineException
from authentik.policies.expression.models import ExpressionPolicy
from authentik.policies.models import Policy, PolicyBinding, PolicyBindingModel, PolicyEngineMode
from authentik.policies.tests.test_process import clear_policy_cache
@ -93,7 +94,7 @@ class TestPolicyEngine(TestCase):
"""Test invalid policy type"""
pbm = PolicyBindingModel.objects.create()
PolicyBinding.objects.create(target=pbm, policy=self.policy_wrong_type, order=0)
with self.assertRaises(TypeError):
with self.assertRaises(PolicyEngineException):
engine = PolicyEngine(pbm, self.user)
engine.build()

View File

@ -43,9 +43,10 @@ type Application struct {
outpostName string
sessionName string
sessions sessions.Store
proxyConfig api.ProxyOutpostConfig
httpClient *http.Client
sessions sessions.Store
proxyConfig api.ProxyOutpostConfig
httpClient *http.Client
publicHostHTTPClient *http.Client
log *log.Entry
mux *mux.Router
@ -110,25 +111,27 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A
}
mux := mux.NewRouter()
// Save cookie name, based on hashed client ID
h := sha256.New()
bs := string(h.Sum([]byte(*p.ClientId)))
sessionName := fmt.Sprintf("authentik_proxy_%s", bs[:8])
a := &Application{
Host: externalHost.Host,
log: muxLogger,
outpostName: server.API().Outpost.Name,
sessionName: sessionName,
endpoint: endpoint,
oauthConfig: oauth2Config,
tokenVerifier: verifier,
proxyConfig: p,
httpClient: c,
mux: mux,
errorTemplates: templates.GetTemplates(),
ak: server.API(),
authHeaderCache: ttlcache.New(ttlcache.WithDisableTouchOnHit[string, Claims]()),
srv: server,
Host: externalHost.Host,
log: muxLogger,
outpostName: server.API().Outpost.Name,
sessionName: sessionName,
endpoint: endpoint,
oauthConfig: oauth2Config,
tokenVerifier: verifier,
proxyConfig: p,
httpClient: c,
publicHostHTTPClient: web.NewHostInterceptor(c, server.API().Outpost.Config["authentik_host"].(string)),
mux: mux,
errorTemplates: templates.GetTemplates(),
ak: server.API(),
authHeaderCache: ttlcache.New(ttlcache.WithDisableTouchOnHit[string, Claims]()),
srv: server,
}
go a.authHeaderCache.Start()
a.sessions = a.getStore(p, externalHost)

View File

@ -64,7 +64,6 @@ func GetOIDCEndpoint(p api.ProxyOutpostConfig, authentikHost string, embedded bo
ep.AuthURL = updateURL(authUrl, aku.Scheme, aku.Host)
ep.EndSessionEndpoint = updateURL(endUrl, aku.Scheme, aku.Host)
ep.JwksUri = updateURL(jwksUrl, aku.Scheme, aku.Host)
ep.TokenURL = updateURL(tokenUrl, aku.Scheme, aku.Host)
ep.Issuer = updateURL(ep.Issuer, aku.Scheme, aku.Host)
return ep
}

View File

@ -24,7 +24,7 @@ func (a *Application) redeemCallback(savedState string, u *url.URL, c context.Co
return nil, fmt.Errorf("blank code")
}
ctx := context.WithValue(c, oauth2.HTTPClient, a.httpClient)
ctx := context.WithValue(c, oauth2.HTTPClient, a.publicHostHTTPClient)
// Verify state and errors.
oauth2Token, err := a.oauthConfig.Exchange(ctx, code)
if err != nil {

View File

@ -0,0 +1,31 @@
package web
import (
"net/http"
"net/url"
log "github.com/sirupsen/logrus"
)
type hostInterceptor struct {
inner http.RoundTripper
host string
}
func (t hostInterceptor) RoundTrip(r *http.Request) (*http.Response, error) {
r.Host = t.host
return t.inner.RoundTrip(r)
}
func NewHostInterceptor(inner *http.Client, host string) *http.Client {
aku, err := url.Parse(host)
if err != nil {
log.WithField("host", host).WithError(err).Warn("failed to parse host")
}
return &http.Client{
Transport: hostInterceptor{
inner: inner.Transport,
host: aku.Host,
},
}
}