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:
parent
925477b3a2
commit
ec42b597ab
|
@ -43,6 +43,7 @@ def clean_expired_models(self: MonitoredTask):
|
||||||
amount = 0
|
amount = 0
|
||||||
for session in AuthenticatedSession.objects.all():
|
for session in AuthenticatedSession.objects.all():
|
||||||
cache_key = f"{KEY_PREFIX}{session.session_key}"
|
cache_key = f"{KEY_PREFIX}{session.session_key}"
|
||||||
|
value = None
|
||||||
try:
|
try:
|
||||||
value = cache.get(cache_key)
|
value = cache.get(cache_key)
|
||||||
# pylint: disable=broad-except
|
# pylint: disable=broad-except
|
||||||
|
|
|
@ -5,6 +5,7 @@ from django.test import TestCase
|
||||||
from authentik.core.models import User
|
from authentik.core.models import User
|
||||||
from authentik.policies.dummy.models import DummyPolicy
|
from authentik.policies.dummy.models import DummyPolicy
|
||||||
from authentik.policies.engine import PolicyEngine
|
from authentik.policies.engine import PolicyEngine
|
||||||
|
from authentik.policies.exceptions import PolicyEngineException
|
||||||
from authentik.policies.expression.models import ExpressionPolicy
|
from authentik.policies.expression.models import ExpressionPolicy
|
||||||
from authentik.policies.models import Policy, PolicyBinding, PolicyBindingModel, PolicyEngineMode
|
from authentik.policies.models import Policy, PolicyBinding, PolicyBindingModel, PolicyEngineMode
|
||||||
from authentik.policies.tests.test_process import clear_policy_cache
|
from authentik.policies.tests.test_process import clear_policy_cache
|
||||||
|
@ -93,7 +94,7 @@ class TestPolicyEngine(TestCase):
|
||||||
"""Test invalid policy type"""
|
"""Test invalid policy type"""
|
||||||
pbm = PolicyBindingModel.objects.create()
|
pbm = PolicyBindingModel.objects.create()
|
||||||
PolicyBinding.objects.create(target=pbm, policy=self.policy_wrong_type, order=0)
|
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 = PolicyEngine(pbm, self.user)
|
||||||
engine.build()
|
engine.build()
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,10 @@ type Application struct {
|
||||||
outpostName string
|
outpostName string
|
||||||
sessionName string
|
sessionName string
|
||||||
|
|
||||||
sessions sessions.Store
|
sessions sessions.Store
|
||||||
proxyConfig api.ProxyOutpostConfig
|
proxyConfig api.ProxyOutpostConfig
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
|
publicHostHTTPClient *http.Client
|
||||||
|
|
||||||
log *log.Entry
|
log *log.Entry
|
||||||
mux *mux.Router
|
mux *mux.Router
|
||||||
|
@ -110,25 +111,27 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A
|
||||||
}
|
}
|
||||||
mux := mux.NewRouter()
|
mux := mux.NewRouter()
|
||||||
|
|
||||||
|
// Save cookie name, based on hashed client ID
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
bs := string(h.Sum([]byte(*p.ClientId)))
|
bs := string(h.Sum([]byte(*p.ClientId)))
|
||||||
sessionName := fmt.Sprintf("authentik_proxy_%s", bs[:8])
|
sessionName := fmt.Sprintf("authentik_proxy_%s", bs[:8])
|
||||||
|
|
||||||
a := &Application{
|
a := &Application{
|
||||||
Host: externalHost.Host,
|
Host: externalHost.Host,
|
||||||
log: muxLogger,
|
log: muxLogger,
|
||||||
outpostName: server.API().Outpost.Name,
|
outpostName: server.API().Outpost.Name,
|
||||||
sessionName: sessionName,
|
sessionName: sessionName,
|
||||||
endpoint: endpoint,
|
endpoint: endpoint,
|
||||||
oauthConfig: oauth2Config,
|
oauthConfig: oauth2Config,
|
||||||
tokenVerifier: verifier,
|
tokenVerifier: verifier,
|
||||||
proxyConfig: p,
|
proxyConfig: p,
|
||||||
httpClient: c,
|
httpClient: c,
|
||||||
mux: mux,
|
publicHostHTTPClient: web.NewHostInterceptor(c, server.API().Outpost.Config["authentik_host"].(string)),
|
||||||
errorTemplates: templates.GetTemplates(),
|
mux: mux,
|
||||||
ak: server.API(),
|
errorTemplates: templates.GetTemplates(),
|
||||||
authHeaderCache: ttlcache.New(ttlcache.WithDisableTouchOnHit[string, Claims]()),
|
ak: server.API(),
|
||||||
srv: server,
|
authHeaderCache: ttlcache.New(ttlcache.WithDisableTouchOnHit[string, Claims]()),
|
||||||
|
srv: server,
|
||||||
}
|
}
|
||||||
go a.authHeaderCache.Start()
|
go a.authHeaderCache.Start()
|
||||||
a.sessions = a.getStore(p, externalHost)
|
a.sessions = a.getStore(p, externalHost)
|
||||||
|
|
|
@ -64,7 +64,6 @@ func GetOIDCEndpoint(p api.ProxyOutpostConfig, authentikHost string, embedded bo
|
||||||
ep.AuthURL = updateURL(authUrl, aku.Scheme, aku.Host)
|
ep.AuthURL = updateURL(authUrl, aku.Scheme, aku.Host)
|
||||||
ep.EndSessionEndpoint = updateURL(endUrl, aku.Scheme, aku.Host)
|
ep.EndSessionEndpoint = updateURL(endUrl, aku.Scheme, aku.Host)
|
||||||
ep.JwksUri = updateURL(jwksUrl, 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)
|
ep.Issuer = updateURL(ep.Issuer, aku.Scheme, aku.Host)
|
||||||
return ep
|
return ep
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ func (a *Application) redeemCallback(savedState string, u *url.URL, c context.Co
|
||||||
return nil, fmt.Errorf("blank code")
|
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.
|
// Verify state and errors.
|
||||||
oauth2Token, err := a.oauthConfig.Exchange(ctx, code)
|
oauth2Token, err := a.oauthConfig.Exchange(ctx, code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue