mirror of
https://github.com/nais/wonderwall.git
synced 2026-08-23 21:16:14 +00:00
fix(reverseproxy): strip incoming id-token header for unauthenticated requests
This commit is contained in:
@@ -32,13 +32,13 @@ type ReverseProxySource interface {
|
||||
type ReverseProxy struct {
|
||||
*httputil.ReverseProxy
|
||||
EnableAccessLogs bool
|
||||
IncludeIdToken bool
|
||||
IncludeIDToken bool
|
||||
}
|
||||
|
||||
func NewUpstreamProxy(upstream *urllib.URL, enableAccessLogs bool, includeIdToken bool) *ReverseProxy {
|
||||
func NewUpstreamProxy(upstream *urllib.URL, enableAccessLogs bool, includeIDToken bool) *ReverseProxy {
|
||||
rp := NewReverseProxy(upstream, true)
|
||||
rp.EnableAccessLogs = enableAccessLogs
|
||||
rp.IncludeIdToken = includeIdToken
|
||||
rp.IncludeIDToken = includeIDToken
|
||||
return rp
|
||||
}
|
||||
|
||||
@@ -74,9 +74,12 @@ func NewReverseProxy(upstream *urllib.URL, preserveInboundHostHeader bool) *Reve
|
||||
r.Out.Header.Set("authorization", "Bearer "+accessToken)
|
||||
}
|
||||
|
||||
idToken, ok := mw.IdTokenFrom(r.In.Context())
|
||||
idToken, ok := mw.IDTokenFrom(r.In.Context())
|
||||
if ok {
|
||||
r.Out.Header.Set("X-Wonderwall-Id-Token", idToken)
|
||||
} else {
|
||||
// remove the header if it was set by the client
|
||||
r.Out.Header.Del("X-Wonderwall-Id-Token")
|
||||
}
|
||||
},
|
||||
Transport: httpinternal.Transport(),
|
||||
@@ -140,9 +143,8 @@ func (rp *ReverseProxy) Handler(src ReverseProxySource, w http.ResponseWriter, r
|
||||
if isAuthenticated {
|
||||
ctx = mw.WithAccessToken(ctx, accessToken)
|
||||
span.SetAttributes(attribute.Bool("proxy.with_access_token", true))
|
||||
if rp.IncludeIdToken && sess != nil {
|
||||
idToken := sess.IDToken()
|
||||
ctx = mw.WithIdToken(ctx, idToken)
|
||||
if rp.IncludeIDToken && sess != nil {
|
||||
ctx = mw.WithIDToken(ctx, sess.IDToken())
|
||||
span.SetAttributes(attribute.Bool("proxy.with_id_token", true))
|
||||
}
|
||||
|
||||
|
||||
@@ -444,7 +444,7 @@ func TestReverseProxy(t *testing.T) {
|
||||
assertUpstreamOKResponse(t, resp)
|
||||
})
|
||||
|
||||
t.Run("request should not include idToken by default", func(t *testing.T) {
|
||||
t.Run("request should not include id_token by default", func(t *testing.T) {
|
||||
cfg := mock.Config()
|
||||
cfg.UpstreamHost = up.URL.Host
|
||||
idp := mock.NewIdentityProvider(cfg)
|
||||
@@ -464,7 +464,7 @@ func TestReverseProxy(t *testing.T) {
|
||||
assertUpstreamOKResponse(t, resp)
|
||||
})
|
||||
|
||||
t.Run("request should include idToken", func(t *testing.T) {
|
||||
t.Run("request should include id_token", func(t *testing.T) {
|
||||
cfg := mock.Config()
|
||||
cfg.UpstreamHost = up.URL.Host
|
||||
cfg.UpstreamIncludeIdToken = true
|
||||
@@ -484,4 +484,24 @@ func TestReverseProxy(t *testing.T) {
|
||||
resp := get(t, rpClient, idp.RelyingPartyServer.URL)
|
||||
assertUpstreamOKResponse(t, resp)
|
||||
})
|
||||
|
||||
t.Run("request should strip incoming id_token if unauthenticated", func(t *testing.T) {
|
||||
cfg := mock.Config()
|
||||
cfg.UpstreamHost = up.URL.Host
|
||||
cfg.UpstreamIncludeIdToken = true
|
||||
idp := mock.NewIdentityProvider(cfg)
|
||||
defer idp.Close()
|
||||
|
||||
up.SetIdentityProvider(idp)
|
||||
rpClient := idp.RelyingPartyClient()
|
||||
|
||||
up.requestCallback = func(r *http.Request) {
|
||||
assert.Empty(t, r.Header.Get("x-wonderwall-id-token"))
|
||||
}
|
||||
|
||||
resp := get(t, rpClient, idp.RelyingPartyServer.URL, header{
|
||||
"x-wonderwall-id-token", "some-id-token",
|
||||
})
|
||||
assertUpstreamUnauthorizedResponse(t, resp)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ type contextKey string
|
||||
|
||||
const (
|
||||
ctxAccessToken = contextKey("AccessToken")
|
||||
ctxIdToken = contextKey("IdToken")
|
||||
ctxIDToken = contextKey("IDToken")
|
||||
ctxIngress = contextKey("Ingress")
|
||||
ctxPath = contextKey("Path")
|
||||
)
|
||||
@@ -25,13 +25,13 @@ func WithAccessToken(ctx context.Context, accessToken string) context.Context {
|
||||
return context.WithValue(ctx, ctxAccessToken, accessToken)
|
||||
}
|
||||
|
||||
func IdTokenFrom(ctx context.Context) (string, bool) {
|
||||
idToken, ok := ctx.Value(ctxIdToken).(string)
|
||||
func IDTokenFrom(ctx context.Context) (string, bool) {
|
||||
idToken, ok := ctx.Value(ctxIDToken).(string)
|
||||
return idToken, ok
|
||||
}
|
||||
|
||||
func WithIdToken(ctx context.Context, idToken string) context.Context {
|
||||
return context.WithValue(ctx, ctxIdToken, idToken)
|
||||
func WithIDToken(ctx context.Context, idToken string) context.Context {
|
||||
return context.WithValue(ctx, ctxIDToken, idToken)
|
||||
}
|
||||
|
||||
func IngressFrom(ctx context.Context) (ingress.Ingress, bool) {
|
||||
|
||||
Reference in New Issue
Block a user