mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-21 06:53:04 +02:00
Merge pull request #692 from james-d-elliott/feat-forward-auth-improvements
feat(sso): forward auth improvements
This commit is contained in:
commit
38cfab4a09
39
src/go.mod
39
src/go.mod
@ -18,33 +18,16 @@ require (
|
|||||||
github.com/microcosm-cc/bluemonday v1.0.26
|
github.com/microcosm-cc/bluemonday v1.0.26
|
||||||
github.com/monperrus/crawler-user-agents v1.1.0
|
github.com/monperrus/crawler-user-agents v1.1.0
|
||||||
github.com/shirou/gopsutil/v4 v4.25.1
|
github.com/shirou/gopsutil/v4 v4.25.1
|
||||||
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
golang.org/x/net v0.33.0
|
golang.org/x/net v0.33.0
|
||||||
|
golang.org/x/oauth2 v0.24.0
|
||||||
golang.org/x/text v0.21.0
|
golang.org/x/text v0.21.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/auth v0.13.0 // indirect
|
cloud.google.com/go/auth v0.13.0 // indirect
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect
|
cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect
|
|
||||||
github.com/benbjohnson/clock v1.3.0 // indirect
|
|
||||||
github.com/ebitengine/purego v0.8.2 // indirect
|
|
||||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
|
||||||
github.com/golang/snappy v0.0.1 // indirect
|
|
||||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.128 // indirect
|
|
||||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
|
||||||
github.com/peterhellberg/link v1.2.0 // indirect
|
|
||||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
|
||||||
github.com/shopspring/decimal v1.3.1 // indirect
|
|
||||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
|
||||||
github.com/vultr/govultr/v3 v3.9.1 // indirect
|
|
||||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
|
||||||
go.mongodb.org/mongo-driver v1.12.0 // indirect
|
|
||||||
golang.org/x/sys v0.28.0 // indirect
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
|
||||||
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
||||||
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
|
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
|
||||||
@ -53,6 +36,7 @@ require (
|
|||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect
|
||||||
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect
|
||||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||||
github.com/Azure/go-autorest/autorest v0.11.29 // indirect
|
github.com/Azure/go-autorest/autorest v0.11.29 // indirect
|
||||||
github.com/Azure/go-autorest/autorest/adal v0.9.22 // indirect
|
github.com/Azure/go-autorest/autorest/adal v0.9.22 // indirect
|
||||||
@ -82,6 +66,7 @@ require (
|
|||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.3 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.3 // indirect
|
||||||
github.com/aws/smithy-go v1.22.1 // indirect
|
github.com/aws/smithy-go v1.22.1 // indirect
|
||||||
github.com/aymerick/douceur v0.2.0 // indirect
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
|
github.com/benbjohnson/clock v1.3.0 // indirect
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||||
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
@ -94,6 +79,7 @@ require (
|
|||||||
github.com/dnsimple/dnsimple-go v1.7.0 // indirect
|
github.com/dnsimple/dnsimple-go v1.7.0 // indirect
|
||||||
github.com/docker/go-connections v0.5.0 // indirect
|
github.com/docker/go-connections v0.5.0 // indirect
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
|
github.com/ebitengine/purego v0.8.2 // indirect
|
||||||
github.com/fatih/structs v1.1.0 // indirect
|
github.com/fatih/structs v1.1.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||||
@ -102,11 +88,14 @@ require (
|
|||||||
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
|
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
|
||||||
github.com/go-logr/logr v1.4.2 // indirect
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
github.com/go-resty/resty/v2 v2.16.2 // indirect
|
github.com/go-resty/resty/v2 v2.16.2 // indirect
|
||||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||||
github.com/goccy/go-json v0.10.4 // indirect
|
github.com/goccy/go-json v0.10.4 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
|
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||||
|
github.com/golang/snappy v0.0.1 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/s2a-go v0.1.8 // indirect
|
github.com/google/s2a-go v0.1.8 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
||||||
@ -119,6 +108,7 @@ require (
|
|||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||||
|
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.128 // indirect
|
||||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
|
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
|
||||||
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
|
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
|
||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
@ -155,29 +145,36 @@ require (
|
|||||||
github.com/nzdjb/go-metaname v1.0.0 // indirect
|
github.com/nzdjb/go-metaname v1.0.0 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||||
|
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
||||||
github.com/ovh/go-ovh v1.6.0 // indirect
|
github.com/ovh/go-ovh v1.6.0 // indirect
|
||||||
|
github.com/peterhellberg/link v1.2.0 // indirect
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||||
github.com/pquerna/otp v1.4.0 // indirect
|
github.com/pquerna/otp v1.4.0 // indirect
|
||||||
github.com/sacloud/api-client-go v0.2.10 // indirect
|
github.com/sacloud/api-client-go v0.2.10 // indirect
|
||||||
github.com/sacloud/go-http v0.1.8 // indirect
|
github.com/sacloud/go-http v0.1.8 // indirect
|
||||||
github.com/sacloud/iaas-api-go v1.14.0 // indirect
|
github.com/sacloud/iaas-api-go v1.14.0 // indirect
|
||||||
github.com/sacloud/packages-go v0.0.10 // indirect
|
github.com/sacloud/packages-go v0.0.10 // indirect
|
||||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 // indirect
|
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 // indirect
|
||||||
|
github.com/shopspring/decimal v1.3.1 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
|
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
|
||||||
github.com/softlayer/softlayer-go v1.1.7 // indirect
|
github.com/softlayer/softlayer-go v1.1.7 // indirect
|
||||||
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
|
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
|
||||||
github.com/spf13/cast v1.6.0 // indirect
|
github.com/spf13/cast v1.6.0 // indirect
|
||||||
github.com/stretchr/testify v1.10.0 // indirect
|
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1065 // indirect
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1065 // indirect
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1065 // indirect
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1065 // indirect
|
||||||
|
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||||
github.com/transip/gotransip/v6 v6.26.0 // indirect
|
github.com/transip/gotransip/v6 v6.26.0 // indirect
|
||||||
github.com/ultradns/ultradns-go-sdk v1.8.0-20241010134910-243eeec // indirect
|
github.com/ultradns/ultradns-go-sdk v1.8.0-20241010134910-243eeec // indirect
|
||||||
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
|
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
|
||||||
|
github.com/vultr/govultr/v3 v3.9.1 // indirect
|
||||||
github.com/yandex-cloud/go-genproto v0.0.0-20241220122821-aeb3b05efd1c // indirect
|
github.com/yandex-cloud/go-genproto v0.0.0-20241220122821-aeb3b05efd1c // indirect
|
||||||
github.com/yandex-cloud/go-sdk v0.0.0-20241220131134-2393e243c134 // indirect
|
github.com/yandex-cloud/go-sdk v0.0.0-20241220131134-2393e243c134 // indirect
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||||
|
go.mongodb.org/mongo-driver v1.12.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.29.0 // indirect
|
go.opentelemetry.io/otel v1.29.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 // indirect
|
||||||
@ -187,8 +184,8 @@ require (
|
|||||||
go.uber.org/ratelimit v0.3.0 // indirect
|
go.uber.org/ratelimit v0.3.0 // indirect
|
||||||
golang.org/x/crypto v0.31.0 // indirect
|
golang.org/x/crypto v0.31.0 // indirect
|
||||||
golang.org/x/mod v0.22.0 // indirect
|
golang.org/x/mod v0.22.0 // indirect
|
||||||
golang.org/x/oauth2 v0.24.0 // indirect
|
|
||||||
golang.org/x/sync v0.10.0 // indirect
|
golang.org/x/sync v0.10.0 // indirect
|
||||||
|
golang.org/x/sys v0.28.0 // indirect
|
||||||
golang.org/x/time v0.8.0 // indirect
|
golang.org/x/time v0.8.0 // indirect
|
||||||
golang.org/x/tools v0.28.0 // indirect
|
golang.org/x/tools v0.28.0 // indirect
|
||||||
google.golang.org/api v0.214.0 // indirect
|
google.golang.org/api v0.214.0 // indirect
|
||||||
|
@ -11,6 +11,7 @@ const (
|
|||||||
DatabaseKeyResponseHeaders = "responseHeaders"
|
DatabaseKeyResponseHeaders = "responseHeaders"
|
||||||
DatabaseKeyResponseClientHeaders = "responseClientHeaders"
|
DatabaseKeyResponseClientHeaders = "responseClientHeaders"
|
||||||
DatabaseKeyRequestHeaders = "requestHeaders"
|
DatabaseKeyRequestHeaders = "requestHeaders"
|
||||||
|
DatabaseKeyRequestIncludedCookies = "requestIncludedCookies"
|
||||||
DatabaseKeyRequestExcludedCookies = "requestExcludedCookies"
|
DatabaseKeyRequestExcludedCookies = "requestExcludedCookies"
|
||||||
|
|
||||||
HeaderXForwardedProto = "X-Forwarded-Proto"
|
HeaderXForwardedProto = "X-Forwarded-Proto"
|
||||||
|
@ -3,7 +3,6 @@ package forward
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -28,6 +27,10 @@ type AuthRouterOptions struct {
|
|||||||
// headers are copied.
|
// headers are copied.
|
||||||
RequestHeaders []string
|
RequestHeaders []string
|
||||||
|
|
||||||
|
// RequestIncludedCookies is a list of cookie keys that if defined will be the only cookies sent in the request to
|
||||||
|
// the authorization server.
|
||||||
|
RequestIncludedCookies []string
|
||||||
|
|
||||||
// RequestExcludedCookies is a list of cookie keys that should be removed from every request sent to the upstream.
|
// RequestExcludedCookies is a list of cookie keys that should be removed from every request sent to the upstream.
|
||||||
RequestExcludedCookies []string
|
RequestExcludedCookies []string
|
||||||
|
|
||||||
@ -47,16 +50,18 @@ func NewAuthRouter(options *AuthRouterOptions) *AuthRouter {
|
|||||||
//Read settings from database if available.
|
//Read settings from database if available.
|
||||||
options.Database.Read(DatabaseTable, DatabaseKeyAddress, &options.Address)
|
options.Database.Read(DatabaseTable, DatabaseKeyAddress, &options.Address)
|
||||||
|
|
||||||
responseHeaders, responseClientHeaders, requestHeaders, requestExcludedCookies := "", "", "", ""
|
responseHeaders, responseClientHeaders, requestHeaders, requestIncludedCookies, requestExcludedCookies := "", "", "", "", ""
|
||||||
|
|
||||||
options.Database.Read(DatabaseTable, DatabaseKeyResponseHeaders, &responseHeaders)
|
options.Database.Read(DatabaseTable, DatabaseKeyResponseHeaders, &responseHeaders)
|
||||||
options.Database.Read(DatabaseTable, DatabaseKeyResponseClientHeaders, &responseClientHeaders)
|
options.Database.Read(DatabaseTable, DatabaseKeyResponseClientHeaders, &responseClientHeaders)
|
||||||
options.Database.Read(DatabaseTable, DatabaseKeyRequestHeaders, &requestHeaders)
|
options.Database.Read(DatabaseTable, DatabaseKeyRequestHeaders, &requestHeaders)
|
||||||
|
options.Database.Read(DatabaseTable, DatabaseKeyRequestIncludedCookies, &requestIncludedCookies)
|
||||||
options.Database.Read(DatabaseTable, DatabaseKeyRequestExcludedCookies, &requestExcludedCookies)
|
options.Database.Read(DatabaseTable, DatabaseKeyRequestExcludedCookies, &requestExcludedCookies)
|
||||||
|
|
||||||
options.ResponseHeaders = strings.Split(responseHeaders, ",")
|
options.ResponseHeaders = strings.Split(responseHeaders, ",")
|
||||||
options.ResponseClientHeaders = strings.Split(responseClientHeaders, ",")
|
options.ResponseClientHeaders = strings.Split(responseClientHeaders, ",")
|
||||||
options.RequestHeaders = strings.Split(requestHeaders, ",")
|
options.RequestHeaders = strings.Split(requestHeaders, ",")
|
||||||
|
options.RequestIncludedCookies = strings.Split(requestIncludedCookies, ",")
|
||||||
options.RequestExcludedCookies = strings.Split(requestExcludedCookies, ",")
|
options.RequestExcludedCookies = strings.Split(requestExcludedCookies, ",")
|
||||||
|
|
||||||
return &AuthRouter{
|
return &AuthRouter{
|
||||||
@ -82,11 +87,12 @@ func (ar *AuthRouter) HandleAPIOptions(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ar *AuthRouter) handleOptionsGET(w http.ResponseWriter, r *http.Request) {
|
func (ar *AuthRouter) handleOptionsGET(w http.ResponseWriter, r *http.Request) {
|
||||||
js, _ := json.Marshal(map[string]interface{}{
|
js, _ := json.Marshal(map[string]any{
|
||||||
DatabaseKeyAddress: ar.options.Address,
|
DatabaseKeyAddress: ar.options.Address,
|
||||||
DatabaseKeyResponseHeaders: ar.options.ResponseHeaders,
|
DatabaseKeyResponseHeaders: ar.options.ResponseHeaders,
|
||||||
DatabaseKeyResponseClientHeaders: ar.options.ResponseClientHeaders,
|
DatabaseKeyResponseClientHeaders: ar.options.ResponseClientHeaders,
|
||||||
DatabaseKeyRequestHeaders: ar.options.RequestHeaders,
|
DatabaseKeyRequestHeaders: ar.options.RequestHeaders,
|
||||||
|
DatabaseKeyRequestIncludedCookies: ar.options.RequestIncludedCookies,
|
||||||
DatabaseKeyRequestExcludedCookies: ar.options.RequestExcludedCookies,
|
DatabaseKeyRequestExcludedCookies: ar.options.RequestExcludedCookies,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -108,6 +114,7 @@ func (ar *AuthRouter) handleOptionsPOST(w http.ResponseWriter, r *http.Request)
|
|||||||
responseHeaders, _ := utils.PostPara(r, DatabaseKeyResponseHeaders)
|
responseHeaders, _ := utils.PostPara(r, DatabaseKeyResponseHeaders)
|
||||||
responseClientHeaders, _ := utils.PostPara(r, DatabaseKeyResponseClientHeaders)
|
responseClientHeaders, _ := utils.PostPara(r, DatabaseKeyResponseClientHeaders)
|
||||||
requestHeaders, _ := utils.PostPara(r, DatabaseKeyRequestHeaders)
|
requestHeaders, _ := utils.PostPara(r, DatabaseKeyRequestHeaders)
|
||||||
|
requestIncludedCookies, _ := utils.PostPara(r, DatabaseKeyRequestIncludedCookies)
|
||||||
requestExcludedCookies, _ := utils.PostPara(r, DatabaseKeyRequestExcludedCookies)
|
requestExcludedCookies, _ := utils.PostPara(r, DatabaseKeyRequestExcludedCookies)
|
||||||
|
|
||||||
// Write changes to runtime
|
// Write changes to runtime
|
||||||
@ -115,6 +122,7 @@ func (ar *AuthRouter) handleOptionsPOST(w http.ResponseWriter, r *http.Request)
|
|||||||
ar.options.ResponseHeaders = strings.Split(responseHeaders, ",")
|
ar.options.ResponseHeaders = strings.Split(responseHeaders, ",")
|
||||||
ar.options.ResponseClientHeaders = strings.Split(responseClientHeaders, ",")
|
ar.options.ResponseClientHeaders = strings.Split(responseClientHeaders, ",")
|
||||||
ar.options.RequestHeaders = strings.Split(requestHeaders, ",")
|
ar.options.RequestHeaders = strings.Split(requestHeaders, ",")
|
||||||
|
ar.options.RequestIncludedCookies = strings.Split(requestIncludedCookies, ",")
|
||||||
ar.options.RequestExcludedCookies = strings.Split(requestExcludedCookies, ",")
|
ar.options.RequestExcludedCookies = strings.Split(requestExcludedCookies, ",")
|
||||||
|
|
||||||
// Write changes to database
|
// Write changes to database
|
||||||
@ -122,6 +130,7 @@ func (ar *AuthRouter) handleOptionsPOST(w http.ResponseWriter, r *http.Request)
|
|||||||
ar.options.Database.Write(DatabaseTable, DatabaseKeyResponseHeaders, responseHeaders)
|
ar.options.Database.Write(DatabaseTable, DatabaseKeyResponseHeaders, responseHeaders)
|
||||||
ar.options.Database.Write(DatabaseTable, DatabaseKeyResponseClientHeaders, responseClientHeaders)
|
ar.options.Database.Write(DatabaseTable, DatabaseKeyResponseClientHeaders, responseClientHeaders)
|
||||||
ar.options.Database.Write(DatabaseTable, DatabaseKeyRequestHeaders, requestHeaders)
|
ar.options.Database.Write(DatabaseTable, DatabaseKeyRequestHeaders, requestHeaders)
|
||||||
|
ar.options.Database.Write(DatabaseTable, DatabaseKeyRequestIncludedCookies, requestIncludedCookies)
|
||||||
ar.options.Database.Write(DatabaseTable, DatabaseKeyRequestExcludedCookies, requestExcludedCookies)
|
ar.options.Database.Write(DatabaseTable, DatabaseKeyRequestExcludedCookies, requestExcludedCookies)
|
||||||
|
|
||||||
utils.SendOK(w)
|
utils.SendOK(w)
|
||||||
@ -136,60 +145,40 @@ func (ar *AuthRouter) handleOptionsMethodNotAllowed(w http.ResponseWriter, r *ht
|
|||||||
// HandleAuthProviderRouting is the internal handler for Forward Auth authentication.
|
// HandleAuthProviderRouting is the internal handler for Forward Auth authentication.
|
||||||
func (ar *AuthRouter) HandleAuthProviderRouting(w http.ResponseWriter, r *http.Request) error {
|
func (ar *AuthRouter) HandleAuthProviderRouting(w http.ResponseWriter, r *http.Request) error {
|
||||||
if ar.options.Address == "" {
|
if ar.options.Address == "" {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
return ar.handle500Error(w, nil, "Address not set")
|
||||||
|
|
||||||
ar.options.Logger.PrintAndLog(LogTitle, "Address not set", nil)
|
|
||||||
|
|
||||||
return ErrInternalServerError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a request to Authz Server to verify the request
|
// Make a request to Authz Server to verify the request
|
||||||
|
// TODO: Add opt-in support for copying the request body to the forward auth request. Currently it's just an
|
||||||
|
// empty body which is usually fine in most instances. It's likely best to see if anyone wants this feature
|
||||||
|
// as I'm unaware of any specific forward auth implementation that needs it.
|
||||||
req, err := http.NewRequest(http.MethodGet, ar.options.Address, nil)
|
req, err := http.NewRequest(http.MethodGet, ar.options.Address, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
return ar.handle500Error(w, err, "Unable to create request")
|
||||||
|
|
||||||
ar.options.Logger.PrintAndLog(LogTitle, "Unable to create request", err)
|
|
||||||
|
|
||||||
return ErrInternalServerError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add opt-in support for copying the request body to the forward auth request.
|
|
||||||
headerCopyIncluded(r.Header, req.Header, ar.options.RequestHeaders, true)
|
headerCopyIncluded(r.Header, req.Header, ar.options.RequestHeaders, true)
|
||||||
|
headerCookieRedact(r, ar.options.RequestIncludedCookies, false)
|
||||||
|
|
||||||
// TODO: Add support for upstream headers.
|
// TODO: Add support for headers from upstream proxies. This will likely involve implementing some form of
|
||||||
|
// proxy specific trust system within Zoraxy.
|
||||||
rSetForwardedHeaders(r, req)
|
rSetForwardedHeaders(r, req)
|
||||||
|
|
||||||
// Make the Authz Request.
|
// Make the Authz Request.
|
||||||
respForwarded, err := ar.client.Do(req)
|
respForwarded, err := ar.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
return ar.handle500Error(w, err, "Unable to perform forwarded auth due to a request error")
|
||||||
|
|
||||||
ar.options.Logger.PrintAndLog(LogTitle, "Unable to perform forwarded auth due to a request error", err)
|
|
||||||
|
|
||||||
return ErrInternalServerError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defer respForwarded.Body.Close()
|
defer respForwarded.Body.Close()
|
||||||
|
|
||||||
body, err := io.ReadAll(respForwarded.Body)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
||||||
|
|
||||||
ar.options.Logger.PrintAndLog(LogTitle, "Unable to read response to forward auth request", err)
|
|
||||||
|
|
||||||
return ErrInternalServerError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Responses within the 200-299 range are considered successful and allow the proxy to handle the request.
|
// Responses within the 200-299 range are considered successful and allow the proxy to handle the request.
|
||||||
if respForwarded.StatusCode >= http.StatusOK && respForwarded.StatusCode < http.StatusMultipleChoices {
|
if respForwarded.StatusCode >= http.StatusOK && respForwarded.StatusCode < http.StatusMultipleChoices {
|
||||||
if len(ar.options.ResponseClientHeaders) != 0 {
|
if len(ar.options.ResponseClientHeaders) != 0 {
|
||||||
headerCopyIncluded(respForwarded.Header, w.Header(), ar.options.ResponseClientHeaders, false)
|
headerCopyIncluded(respForwarded.Header, w.Header(), ar.options.ResponseClientHeaders, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ar.options.RequestExcludedCookies) != 0 {
|
headerCookieRedact(r, ar.options.RequestExcludedCookies, true)
|
||||||
// If the user has specified a list of cookies to be removed from the request, deterministically remove them.
|
|
||||||
headerCookieRedact(r, ar.options.RequestExcludedCookies)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ar.options.ResponseHeaders) != 0 {
|
if len(ar.options.ResponseHeaders) != 0 {
|
||||||
// Copy specific user-specified headers from the response of the forward auth request to the request sent to the
|
// Copy specific user-specified headers from the response of the forward auth request to the request sent to the
|
||||||
@ -197,138 +186,32 @@ func (ar *AuthRouter) HandleAuthProviderRouting(w http.ResponseWriter, r *http.R
|
|||||||
headerCopyIncluded(respForwarded.Header, w.Header(), ar.options.ResponseHeaders, false)
|
headerCopyIncluded(respForwarded.Header, w.Header(), ar.options.ResponseHeaders, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the request to the proxy for forwarding to the backend.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the response.
|
// Copy the unsuccessful response.
|
||||||
headerCopyExcluded(respForwarded.Header, w.Header(), nil)
|
headerCopyExcluded(respForwarded.Header, w.Header(), nil)
|
||||||
|
|
||||||
w.WriteHeader(respForwarded.StatusCode)
|
w.WriteHeader(respForwarded.StatusCode)
|
||||||
|
|
||||||
|
body, err := io.ReadAll(respForwarded.Body)
|
||||||
|
if err != nil {
|
||||||
|
return ar.handle500Error(w, err, "Unable to read response to forward auth request")
|
||||||
|
}
|
||||||
|
|
||||||
if _, err = w.Write(body); err != nil {
|
if _, err = w.Write(body); err != nil {
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
return ar.handle500Error(w, err, "Unable to write response")
|
||||||
|
|
||||||
ar.options.Logger.PrintAndLog(LogTitle, "Unable to write response", err)
|
|
||||||
|
|
||||||
return ErrInternalServerError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ErrUnauthorized
|
return ErrUnauthorized
|
||||||
}
|
}
|
||||||
|
|
||||||
func scheme(r *http.Request) string {
|
// handle500Error is func intended on factorizing a commonly repeated functional flow within this provider.
|
||||||
if r.TLS != nil {
|
func (ar *AuthRouter) handle500Error(w http.ResponseWriter, err error, message string) error {
|
||||||
return "https"
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
}
|
|
||||||
|
|
||||||
return "http"
|
ar.options.Logger.PrintAndLog(LogTitle, message, err)
|
||||||
}
|
|
||||||
|
|
||||||
func headerCookieRedact(r *http.Request, excluded []string) {
|
return ErrInternalServerError
|
||||||
original := r.Cookies()
|
|
||||||
|
|
||||||
if len(original) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var cookies []string
|
|
||||||
|
|
||||||
for _, cookie := range original {
|
|
||||||
if stringInSlice(cookie.Name, excluded) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
cookies = append(cookies, cookie.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Header.Set(HeaderCookie, strings.Join(cookies, "; "))
|
|
||||||
}
|
|
||||||
|
|
||||||
func headerCopyExcluded(original, destination http.Header, excludedHeaders []string) {
|
|
||||||
for key, values := range original {
|
|
||||||
// We should never copy the headers in the below list.
|
|
||||||
if stringInSliceFold(key, doNotCopyHeaders) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if stringInSliceFold(key, excludedHeaders) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
destination[key] = append(destination[key], values...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func headerCopyIncluded(original, destination http.Header, includedHeaders []string, allIfEmpty bool) {
|
|
||||||
if allIfEmpty && len(includedHeaders) == 0 {
|
|
||||||
headerCopyAll(original, destination)
|
|
||||||
} else {
|
|
||||||
headerCopyIncludedExact(original, destination, includedHeaders)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func headerCopyAll(original, destination http.Header) {
|
|
||||||
for key, values := range original {
|
|
||||||
// We should never copy the headers in the below list, even if they're in the list provided by a user.
|
|
||||||
if stringInSliceFold(key, doNotCopyHeaders) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
destination[key] = append(destination[key], values...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func headerCopyIncludedExact(original, destination http.Header, keys []string) {
|
|
||||||
for _, key := range keys {
|
|
||||||
// We should never copy the headers in the below list, even if they're in the list provided by a user.
|
|
||||||
if stringInSliceFold(key, doNotCopyHeaders) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if values, ok := original[key]; ok {
|
|
||||||
destination[key] = append(destination[key], values...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringInSlice(needle string, haystack []string) bool {
|
|
||||||
if len(haystack) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range haystack {
|
|
||||||
if needle == v {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringInSliceFold(needle string, haystack []string) bool {
|
|
||||||
if len(haystack) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range haystack {
|
|
||||||
if strings.EqualFold(needle, v) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func rSetForwardedHeaders(r, req *http.Request) {
|
|
||||||
if r.RemoteAddr != "" {
|
|
||||||
before, _, _ := strings.Cut(r.RemoteAddr, ":")
|
|
||||||
|
|
||||||
if ip := net.ParseIP(before); ip != nil {
|
|
||||||
req.Header.Set(HeaderXForwardedFor, ip.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set(HeaderXForwardedMethod, r.Method)
|
|
||||||
req.Header.Set(HeaderXForwardedProto, scheme(r))
|
|
||||||
req.Header.Set(HeaderXForwardedHost, r.Host)
|
|
||||||
req.Header.Set(HeaderXForwardedURI, r.URL.Path)
|
|
||||||
}
|
}
|
||||||
|
137
src/mod/auth/sso/forward/util.go
Normal file
137
src/mod/auth/sso/forward/util.go
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package forward
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func scheme(r *http.Request) string {
|
||||||
|
if r.TLS != nil {
|
||||||
|
return "https"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "http"
|
||||||
|
}
|
||||||
|
|
||||||
|
func headerCookieRedact(r *http.Request, names []string, exclude bool) {
|
||||||
|
if len(names) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
original := r.Cookies()
|
||||||
|
|
||||||
|
if len(original) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var cookies []string
|
||||||
|
|
||||||
|
for _, cookie := range original {
|
||||||
|
if exclude && stringInSlice(cookie.Name, names) {
|
||||||
|
continue
|
||||||
|
} else if !exclude && !stringInSlice(cookie.Name, names) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cookies = append(cookies, cookie.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
value := strings.Join(cookies, "; ")
|
||||||
|
|
||||||
|
r.Header.Set(HeaderCookie, value)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func headerCopyExcluded(original, destination http.Header, excludedHeaders []string) {
|
||||||
|
for key, values := range original {
|
||||||
|
// We should never copy the headers in the below list.
|
||||||
|
if stringInSliceFold(key, doNotCopyHeaders) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if stringInSliceFold(key, excludedHeaders) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
destination[key] = append(destination[key], values...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func headerCopyIncluded(original, destination http.Header, includedHeaders []string, allIfEmpty bool) {
|
||||||
|
if allIfEmpty && len(includedHeaders) == 0 {
|
||||||
|
headerCopyAll(original, destination)
|
||||||
|
} else {
|
||||||
|
headerCopyIncludedExact(original, destination, includedHeaders)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func headerCopyAll(original, destination http.Header) {
|
||||||
|
for key, values := range original {
|
||||||
|
// We should never copy the headers in the below list, even if they're in the list provided by a user.
|
||||||
|
if stringInSliceFold(key, doNotCopyHeaders) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
destination[key] = append(destination[key], values...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func headerCopyIncludedExact(original, destination http.Header, keys []string) {
|
||||||
|
for key, values := range original {
|
||||||
|
// We should never copy the headers in the below list, even if they're in the list provided by a user.
|
||||||
|
if stringInSliceFold(key, doNotCopyHeaders) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !stringInSliceFold(key, keys) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
destination[key] = append(destination[key], values...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringInSlice(needle string, haystack []string) bool {
|
||||||
|
if len(haystack) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range haystack {
|
||||||
|
if needle == v {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringInSliceFold(needle string, haystack []string) bool {
|
||||||
|
if len(haystack) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range haystack {
|
||||||
|
if strings.EqualFold(needle, v) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func rSetForwardedHeaders(r, req *http.Request) {
|
||||||
|
if r.RemoteAddr != "" {
|
||||||
|
before, _, _ := strings.Cut(r.RemoteAddr, ":")
|
||||||
|
|
||||||
|
if ip := net.ParseIP(before); ip != nil {
|
||||||
|
req.Header.Set(HeaderXForwardedFor, ip.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set(HeaderXForwardedMethod, r.Method)
|
||||||
|
req.Header.Set(HeaderXForwardedProto, scheme(r))
|
||||||
|
req.Header.Set(HeaderXForwardedHost, r.Host)
|
||||||
|
req.Header.Set(HeaderXForwardedURI, r.URL.Path)
|
||||||
|
}
|
217
src/mod/auth/sso/forward/util_test.go
Normal file
217
src/mod/auth/sso/forward/util_test.go
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
package forward
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestScheme(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
have *http.Request
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"ShouldHandleDefault",
|
||||||
|
&http.Request{},
|
||||||
|
"http",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ShouldHandleExplicit",
|
||||||
|
&http.Request{
|
||||||
|
TLS: nil,
|
||||||
|
},
|
||||||
|
"http",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ShouldHandleHTTPS",
|
||||||
|
&http.Request{
|
||||||
|
TLS: &tls.ConnectionState{},
|
||||||
|
},
|
||||||
|
"https",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
assert.Equal(t, tc.expected, scheme(tc.have))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHeaderCookieRedact(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
have string
|
||||||
|
names []string
|
||||||
|
expectedInclude string
|
||||||
|
expectedExclude string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"ShouldHandleIncludeEmptyWithoutSettings",
|
||||||
|
"",
|
||||||
|
nil,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ShouldHandleIncludeEmptyWithSettings",
|
||||||
|
"",
|
||||||
|
[]string{"include"},
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ShouldHandleValueWithoutSettings",
|
||||||
|
"include=value; exclude=value",
|
||||||
|
nil,
|
||||||
|
"include=value; exclude=value",
|
||||||
|
"include=value; exclude=value",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ShouldHandleValueWithSettings",
|
||||||
|
"include=value; exclude=value",
|
||||||
|
[]string{"include"},
|
||||||
|
"include=value",
|
||||||
|
"exclude=value",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
var include, exclude *http.Request
|
||||||
|
|
||||||
|
include, exclude = &http.Request{Header: http.Header{}}, &http.Request{Header: http.Header{}}
|
||||||
|
|
||||||
|
if tc.have != "" {
|
||||||
|
include.Header.Set(HeaderCookie, tc.have)
|
||||||
|
exclude.Header.Set(HeaderCookie, tc.have)
|
||||||
|
}
|
||||||
|
|
||||||
|
headerCookieRedact(include, tc.names, false)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.expectedInclude, include.Header.Get(HeaderCookie))
|
||||||
|
|
||||||
|
headerCookieRedact(exclude, tc.names, true)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.expectedExclude, exclude.Header.Get(HeaderCookie))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHeaderCopyExcluded(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
original http.Header
|
||||||
|
excluded []string
|
||||||
|
expected http.Header
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"ShouldHandleNoSettingsNoHeaders",
|
||||||
|
http.Header{},
|
||||||
|
nil,
|
||||||
|
http.Header{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ShouldHandleNoSettingsWithHeaders",
|
||||||
|
http.Header{
|
||||||
|
"Example": []string{"value", "other"},
|
||||||
|
"Exclude": []string{"value", "other"},
|
||||||
|
HeaderUpgrade: []string{"do", "not", "copy"},
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
http.Header{
|
||||||
|
"Example": []string{"value", "other"},
|
||||||
|
"Exclude": []string{"value", "other"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ShouldHandleSettingsWithHeaders",
|
||||||
|
http.Header{
|
||||||
|
"Example": []string{"value", "other"},
|
||||||
|
"Exclude": []string{"value", "other"},
|
||||||
|
HeaderUpgrade: []string{"do", "not", "copy"},
|
||||||
|
},
|
||||||
|
[]string{"exclude"},
|
||||||
|
http.Header{
|
||||||
|
"Example": []string{"value", "other"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
headers := http.Header{}
|
||||||
|
|
||||||
|
headerCopyExcluded(tc.original, headers, tc.excluded)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.expected, headers)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHeaderCopyIncluded(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
original http.Header
|
||||||
|
included []string
|
||||||
|
expected http.Header
|
||||||
|
expectedAll http.Header
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"ShouldHandleNoSettingsNoHeaders",
|
||||||
|
http.Header{},
|
||||||
|
nil,
|
||||||
|
http.Header{},
|
||||||
|
http.Header{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ShouldHandleNoSettingsWithHeaders",
|
||||||
|
http.Header{
|
||||||
|
"Example": []string{"value", "other"},
|
||||||
|
"Include": []string{"value", "other"},
|
||||||
|
HeaderUpgrade: []string{"do", "not", "copy"},
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
http.Header{},
|
||||||
|
http.Header{
|
||||||
|
"Example": []string{"value", "other"},
|
||||||
|
"Include": []string{"value", "other"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ShouldHandleSettingsWithHeaders",
|
||||||
|
http.Header{
|
||||||
|
"Example": []string{"value", "other"},
|
||||||
|
"Include": []string{"value", "other"},
|
||||||
|
HeaderUpgrade: []string{"do", "not", "copy"},
|
||||||
|
},
|
||||||
|
[]string{"include"},
|
||||||
|
http.Header{
|
||||||
|
"Include": []string{"value", "other"},
|
||||||
|
},
|
||||||
|
http.Header{
|
||||||
|
"Include": []string{"value", "other"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
headers := http.Header{}
|
||||||
|
|
||||||
|
headerCopyIncluded(tc.original, headers, tc.included, false)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.expected, headers)
|
||||||
|
|
||||||
|
headers = http.Header{}
|
||||||
|
|
||||||
|
headerCopyIncluded(tc.original, headers, tc.included, true)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.expectedAll, headers)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li><a href="https://www.authelia.com" rel=”noopener noreferrer” target="_blank">Authelia</a></li>
|
<li><a href="https://www.authelia.com" rel=”noopener noreferrer” target="_blank">Authelia</a></li>
|
||||||
<li><a href="https://goauthentik.io/" rel=”noopener noreferrer” target="_blank">Authentik</a></li>
|
<li><a href="https://goauthentik.io/" rel=”noopener noreferrer” target="_blank">Authentik</a></li>
|
||||||
|
<li><a href="https://oauth2-proxy.github.io/oauth2-proxy/" rel=”noopener noreferrer” target="_blank">OAuth2 Proxy</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<form class="ui form" action="#" id="forwardAuthSettings">
|
<form class="ui form" action="#" id="forwardAuthSettings">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
@ -42,26 +43,43 @@
|
|||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="forwardAuthResponseHeaders">Response Headers</label>
|
<label for="forwardAuthResponseHeaders">Response Headers</label>
|
||||||
<input type="text" id="forwardAuthResponseHeaders" name="forwardAuthResponseHeaders" placeholder="Enter Forward Auth Response Headers">
|
<input type="text" id="forwardAuthResponseHeaders" name="forwardAuthResponseHeaders" placeholder="Enter Forward Auth Response Headers">
|
||||||
<small>Comma separated list of case-insensitive headers to copy from the authorization servers response to the request sent to the backend. If not set no headers are copied. <br>
|
<small>
|
||||||
<strong>Example:</strong> <code>Remote-User,Remote-Groups,Remote-Email,Remote-Name</code></small>
|
Comma separated list of case-insensitive headers to copy from the authorization servers response to the request sent to the backend. If not set no headers are copied. <br>
|
||||||
|
<strong>Example:</strong> <code>Remote-User,Remote-Groups,Remote-Email,Remote-Name</code>
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="forwardAuthResponseClientHeaders">Response Client Headers</label>
|
<label for="forwardAuthResponseClientHeaders">Response Client Headers</label>
|
||||||
<input type="text" id="forwardAuthResponseClientHeaders" name="forwardAuthResponseClientHeaders" placeholder="Enter Forward Auth Response Client Headers">
|
<input type="text" id="forwardAuthResponseClientHeaders" name="forwardAuthResponseClientHeaders" placeholder="Enter Forward Auth Response Client Headers">
|
||||||
<small>Comma separated list of case-insensitive headers to copy from the authorization servers response to the response sent to the client. If not set no headers are copied. <br>
|
<small>
|
||||||
<strong>Example:</strong> <code>Set-Cookie,WWW-Authenticate</code></small>
|
Comma separated list of case-insensitive headers to copy from the authorization servers response to the <b><i>response sent to the client</i></b>. If not set no headers are copied. <br>
|
||||||
|
<strong>Example:</strong> <code>Set-Cookie,WWW-Authenticate</code>
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="forwardAuthRequestHeaders">Request Headers</label>
|
<label for="forwardAuthRequestHeaders">Request Headers</label>
|
||||||
<input type="text" id="forwardAuthRequestHeaders" name="forwardAuthRequestHeaders" placeholder="Enter Forward Auth Request Headers">
|
<input type="text" id="forwardAuthRequestHeaders" name="forwardAuthRequestHeaders" placeholder="Enter Forward Auth Request Headers">
|
||||||
<small>Comma separated list of case-insensitive headers to copy from the original request to the request made to the authorization server. If not set all headers are copied. <br>
|
<small>
|
||||||
<strong>Example:</strong> <code>Cookie,Authorization</code></small>
|
Comma separated list of case-insensitive headers to copy from the original request to the <b><i>request made to the authorization server</i></b>. If not set all headers are copied. <br>
|
||||||
|
<strong>Recommendation:</strong> Generally it's recommended to leave this blank or use the below example for predictable results. <br>
|
||||||
|
<strong>Example:</strong> <code>Accept,X-Requested-With,Cookie,Authorization,Proxy-Authorization</code>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label for="forwardAuthRequestIncludedCookies">Request Included Cookies</label>
|
||||||
|
<input type="text" id="forwardAuthRequestIncludedCookies" name="forwardAuthRequestIncludedCookies" placeholder="Enter Forward Auth Request Included Cookies">
|
||||||
|
<small>
|
||||||
|
Comma separated list of case-sensitive cookie names to copy from the original request to the <b><i>request made to the authorization server</i></b>. If not set all cookies are included. This allows omitting all cookies not required by the authorization server.<br>
|
||||||
|
<strong>Example:</strong> <code>authelia_session,another_session</code>
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="forwardAuthRequestExcludedCookies">Request Excluded Cookies</label>
|
<label for="forwardAuthRequestExcludedCookies">Request Excluded Cookies</label>
|
||||||
<input type="text" id="forwardAuthRequestExcludedCookies" name="forwardAuthRequestExcludedCookies" placeholder="Enter Forward Auth Request Excluded Cookies">
|
<input type="text" id="forwardAuthRequestExcludedCookies" name="forwardAuthRequestExcludedCookies" placeholder="Enter Forward Auth Request Excluded Cookies">
|
||||||
<small>Comma separated list of case-sensitive cookie names to exclude from the request to the backend. If not set no cookies are excluded. <br>
|
<small>
|
||||||
<strong>Example:</strong> <code>authelia_session,another_session</code></small>
|
Comma separated list of case-sensitive cookie names to exclude from the <b><i>request made to the backend application</i></b>. If not set no cookies are excluded. This allows omitting the cookie intended only for the authorization server.<br>
|
||||||
|
<strong>Example:</strong> <code>authelia_session,another_session</code>
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -132,6 +150,7 @@
|
|||||||
$('#forwardAuthResponseHeaders').val(data.responseHeaders.join(","));
|
$('#forwardAuthResponseHeaders').val(data.responseHeaders.join(","));
|
||||||
$('#forwardAuthResponseClientHeaders').val(data.responseClientHeaders.join(","));
|
$('#forwardAuthResponseClientHeaders').val(data.responseClientHeaders.join(","));
|
||||||
$('#forwardAuthRequestHeaders').val(data.requestHeaders.join(","));
|
$('#forwardAuthRequestHeaders').val(data.requestHeaders.join(","));
|
||||||
|
$('#forwardAuthRequestIncludedCookies').val(data.requestIncludedCookies.join(","));
|
||||||
$('#forwardAuthRequestExcludedCookies').val(data.requestExcludedCookies.join(","));
|
$('#forwardAuthRequestExcludedCookies').val(data.requestExcludedCookies.join(","));
|
||||||
},
|
},
|
||||||
error: function(jqXHR, textStatus, errorThrown) {
|
error: function(jqXHR, textStatus, errorThrown) {
|
||||||
@ -170,6 +189,7 @@
|
|||||||
const responseHeaders = $('#forwardAuthResponseHeaders').val();
|
const responseHeaders = $('#forwardAuthResponseHeaders').val();
|
||||||
const responseClientHeaders = $('#forwardAuthResponseClientHeaders').val();
|
const responseClientHeaders = $('#forwardAuthResponseClientHeaders').val();
|
||||||
const requestHeaders = $('#forwardAuthRequestHeaders').val();
|
const requestHeaders = $('#forwardAuthRequestHeaders').val();
|
||||||
|
const requestIncludedCookies = $('#forwardAuthRequestIncludedCookies').val();
|
||||||
const requestExcludedCookies = $('#forwardAuthRequestExcludedCookies').val();
|
const requestExcludedCookies = $('#forwardAuthRequestExcludedCookies').val();
|
||||||
|
|
||||||
console.log(`Updating Forward Auth settings. Address: ${address}. Response Headers: ${responseHeaders}. Response Client Headers: ${responseClientHeaders}. Request Headers: ${requestHeaders}. Request Excluded Cookies: ${requestExcludedCookies}.`);
|
console.log(`Updating Forward Auth settings. Address: ${address}. Response Headers: ${responseHeaders}. Response Client Headers: ${responseClientHeaders}. Request Headers: ${requestHeaders}. Request Excluded Cookies: ${requestExcludedCookies}.`);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user