git.iko.soy/typeable/oauth2-proxy
on master help sign in
feat: migrate all alpha config booleans to pointers

Signed-off-by: Jan Larwig <jan@larwig.com>

commit9d70e04262f91739f78c25f3e61015410e412ceb authorJan Larwig <jan@larwig.com> dateTue 19 Aug 2025, 16:27 (1 year ago) parent5041435
29 files changed+253−165
main_test.go+49−24 oauthproxy_test.go+3−2 pkg/apis/options/header.go+1−1 pkg/apis/options/legacy_options.go+15−14 pkg/apis/options/legacy_options_test.go+44−44 pkg/apis/options/providers.go+14−12 pkg/apis/options/upstreams.go+6−6 pkg/middleware/headers.go+1−1 pkg/middleware/headers_test.go+5−4 pkg/upstream/http.go+3−3 pkg/upstream/http_test.go+11−12 pkg/upstream/proxy.go+2−2 pkg/upstream/proxy_test.go+6−5 pkg/util/ptr/ptr.go+14 pkg/util/ptr/ptr_test.go+38 pkg/validation/options.go+1−1 pkg/validation/options_test.go+3−2 pkg/validation/providers.go+4−3 pkg/validation/upstreams.go+5−5 pkg/validation/upstreams_test.go+6−6 providers/adfs.go+1−1 providers/adfs_test.go+2−1 providers/google.go+3−2 providers/ms_entra_id.go+1−1 providers/ms_entra_id_test.go+4−3 providers/oidc.go+1−1 providers/oidc_test.go+1−1 providers/providers.go+4−4 providers/providers_test.go+5−4
main_test.go+49−24
@@ -7,6 +7,7 @@ import (
77
88 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
99 . "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options/testutil"
10+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
1011 . "github.com/onsi/ginkgo/v2"
1112 . "github.com/onsi/gomega"
1213 "github.com/onsi/gomega/format"
@@ -25,11 +26,12 @@ set_basic_auth="true"
2526basic_auth_password="c3VwZXItc2VjcmV0LXBhc3N3b3Jk"
2627client_id="oauth2-proxy"
2728client_secret="b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK"
29+google_admin_email="admin@example.com"
30+google_target_principal="principal"
2831`
2932
3033 const testAlphaConfig = `
3134upstreamConfig:
32− proxyrawpath: false
3335 upstreams:
3436 - id: /
3537 path: /
@@ -38,8 +40,11 @@ upstreamConfig:
3840 passHostHeader: true
3941 proxyWebSockets: true
4042 timeout: 30s
43+ insecureSkipTLSVerify: false
44+ disableKeepAlives: false
4145injectRequestHeaders:
4246- name: Authorization
47+ preserveRequestValue: false
4348 values:
4449 - claimSource:
4550 claim: user
@@ -47,18 +52,22 @@ injectRequestHeaders:
4752 basicAuthPassword:
4853 value: c3VwZXItc2VjcmV0LXBhc3N3b3Jk
4954- name: X-Forwarded-Groups
55+ preserveRequestValue: false
5056 values:
5157 - claimSource:
5258 claim: groups
5359- name: X-Forwarded-User
60+ preserveRequestValue: false
5461 values:
5562 - claimSource:
5663 claim: user
5764- name: X-Forwarded-Email
65+ preserveRequestValue: false
5866 values:
5967 - claimSource:
6068 claim: email
6169- name: X-Forwarded-Preferred-Username
70+ preserveRequestValue: false
6271 values:
6372 - claimSource:
6473 claim: preferred_username
@@ -77,12 +86,17 @@ providers:
7786 provider: google
7887 clientSecret: b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK
7988 clientID: oauth2-proxy
80− azureConfig:
81− tenant: common
89+ useSystemTrustStore: false
90+ skipClaimsFromProfileURL: false
91+ googleConfig:
92+ adminEmail: admin@example.com
93+ targetPrincipal: principal
94+ useApplicationDefaultCredentials: false
8295 oidcConfig:
8396 groupsClaim: groups
8497 emailClaim: email
8598 userIDClaim: email
99+ insecureSkipIssuerVerification: false
86100 insecureSkipNonce: true
87101 audienceClaims: [aud]
88102 extraAudiences: []
@@ -100,10 +114,6 @@ cookie_secure="false"
100114redirect_url="http://localhost:4180/oauth2/callback"
101115`
102116
103− boolPtr := func(b bool) *bool {
104− return &b
105− }
106−
107117 durationPtr := func(d time.Duration) *time.Duration {
108118 return &d
109119 }
@@ -120,13 +130,15 @@ redirect_url="http://localhost:4180/oauth2/callback"
120130 opts.UpstreamServers = options.UpstreamConfig{
121131 Upstreams: []options.Upstream{
122132 {
123− ID: "/",
124− Path: "/",
125− URI: "http://httpbin",
126− FlushInterval: durationPtr(options.DefaultUpstreamFlushInterval),
127− PassHostHeader: boolPtr(true),
128− ProxyWebSockets: boolPtr(true),
129− Timeout: durationPtr(options.DefaultUpstreamTimeout),
133+ ID: "/",
134+ Path: "/",
135+ URI: "http://httpbin",
136+ FlushInterval: durationPtr(options.DefaultUpstreamFlushInterval),
137+ PassHostHeader: ptr.Ptr(true),
138+ ProxyWebSockets: ptr.Ptr(true),
139+ Timeout: durationPtr(options.DefaultUpstreamTimeout),
140+ InsecureSkipTLSVerify: ptr.Ptr(false),
141+ DisableKeepAlives: ptr.Ptr(false),
130142 },
131143 },
132144 }
@@ -146,25 +158,38 @@ redirect_url="http://localhost:4180/oauth2/callback"
146158 },
147159 }
148160
161+ authHeader.PreserveRequestValue = ptr.Ptr(false)
149162 opts.InjectRequestHeaders = append([]options.Header{authHeader}, opts.InjectRequestHeaders...)
163+
164+ authHeader.PreserveRequestValue = nil
150165 opts.InjectResponseHeaders = append(opts.InjectResponseHeaders, authHeader)
151166
152167 opts.Providers = options.Providers{
153168 options.Provider{
154− ID: "google=oauth2-proxy",
155− Type: "google",
156− ClientSecret: "b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK",
157− ClientID: "oauth2-proxy",
169+ ID: "google=oauth2-proxy",
170+ Type: "google",
171+ ClientSecret: "b2F1dGgyLXByb3h5LWNsaWVudC1zZWNyZXQK",
172+ ClientID: "oauth2-proxy",
173+ UseSystemTrustStore: ptr.Ptr(false),
174+ SkipClaimsFromProfileURL: ptr.Ptr(false),
175+ GoogleConfig: options.GoogleOptions{
176+ AdminEmail: "admin@example.com",
177+ UseApplicationDefaultCredentials: ptr.Ptr(false),
178+ TargetPrincipal: "principal",
179+ },
158180 AzureConfig: options.AzureOptions{
159181 Tenant: "common",
160182 },
161183 OIDCConfig: options.OIDCOptions{
162− GroupsClaim: "groups",
163− EmailClaim: "email",
164− UserIDClaim: "email",
165− AudienceClaims: []string{"aud"},
166− ExtraAudiences: []string{},
167− InsecureSkipNonce: true,
184+ GroupsClaim: "groups",
185+ EmailClaim: "email",
186+ UserIDClaim: "email",
187+ AudienceClaims: []string{"aud"},
188+ ExtraAudiences: []string{},
189+ InsecureSkipNonce: ptr.Ptr(true),
190+ InsecureAllowUnverifiedEmail: ptr.Ptr(false),
191+ InsecureSkipIssuerVerification: ptr.Ptr(false),
192+ SkipDiscovery: ptr.Ptr(false),
168193 },
169194 LoginURLParameters: []options.LoginURLParameter{
170195 {Name: "approval_prompt", Default: []string{"force"}},
oauthproxy_test.go+3−2
@@ -23,6 +23,7 @@ import (
2323 internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc"
2424 sessionscookie "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/sessions/cookie"
2525 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/upstream"
26+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
2627 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/validation"
2728 "github.com/oauth2-proxy/oauth2-proxy/v7/providers"
2829 "github.com/stretchr/testify/assert"
@@ -506,7 +507,7 @@ func TestStaticProxyUpstream(t *testing.T) {
506507 ProxyUpstream: options.Upstream{
507508 ID: "static-proxy",
508509 Path: "/static-proxy",
509− Static: true,
510+ Static: ptr.Ptr(true),
510511 },
511512 })
512513 if err != nil {
@@ -2223,7 +2224,7 @@ func TestTrustedIPs(t *testing.T) {
22232224 {
22242225 ID: "static",
22252226 Path: "/",
2226− Static: true,
2227+ Static: ptr.Ptr(true),
22272228 },
22282229 },
22292230 }
pkg/apis/options/header.go+1−1
@@ -11,7 +11,7 @@ type Header struct {
1111 // should be preserved for the request to the upstream server.
1212 // This option only applies to injected request headers.
1313 // Defaults to false (headers that match this header will be stripped).
14− PreserveRequestValue bool `yaml:"preserveRequestValue"`
14+ PreserveRequestValue *bool `yaml:"preserveRequestValue,omitempty"`
1515
1616 // InsecureSkipHeaderNormalization disables normalizing the header name
1717 // According to RFC 7230 Section 3.2 there aren't any rules about
pkg/apis/options/legacy_options.go+15−14
@@ -9,6 +9,7 @@ import (
99 "time"
1010
1111 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
12+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
1213 "github.com/spf13/pflag"
1314)
1415
@@ -142,12 +143,12 @@ func (l *LegacyUpstreams) convert() (UpstreamConfig, error) {
142143 ID: u.Path,
143144 Path: u.Path,
144145 URI: upstreamString,
145− InsecureSkipTLSVerify: l.SSLUpstreamInsecureSkipVerify,
146+ InsecureSkipTLSVerify: &l.SSLUpstreamInsecureSkipVerify,
146147 PassHostHeader: &l.PassHostHeader,
147148 ProxyWebSockets: &l.ProxyWebSockets,
148149 FlushInterval: &flushInterval,
149150 Timeout: &timeout,
150− DisableKeepAlives: l.DisableKeepAlives,
151+ DisableKeepAlives: &l.DisableKeepAlives,
151152 }
152153
153154 switch u.Scheme {
@@ -164,7 +165,7 @@ func (l *LegacyUpstreams) convert() (UpstreamConfig, error) {
164165 logger.Errorf("unable to convert %q to int, use default \"200\"", u.Host)
165166 responseCode = 200
166167 }
167− upstream.Static = true
168+ upstream.Static = ptr.Ptr(true)
168169 upstream.StaticCode = &responseCode
169170
170171 // This is not allowed to be empty and must be unique
@@ -175,12 +176,12 @@ func (l *LegacyUpstreams) convert() (UpstreamConfig, error) {
175176
176177 // Force defaults compatible with static responses
177178 upstream.URI = ""
178− upstream.InsecureSkipTLSVerify = false
179+ upstream.InsecureSkipTLSVerify = ptr.Ptr(false)
179180 upstream.PassHostHeader = nil
180181 upstream.ProxyWebSockets = nil
181182 upstream.FlushInterval = nil
182183 upstream.Timeout = nil
183− upstream.DisableKeepAlives = false
184+ upstream.DisableKeepAlives = ptr.Ptr(false)
184185 case "unix":
185186 upstream.Path = "/"
186187 }
@@ -253,7 +254,7 @@ func (l *LegacyHeaders) getRequestHeaders() []Header {
253254 }
254255
255256 for i := range requestHeaders {
256− requestHeaders[i].PreserveRequestValue = !l.SkipAuthStripHeaders
257+ requestHeaders[i].PreserveRequestValue = ptr.Ptr(!l.SkipAuthStripHeaders)
257258 }
258259
259260 return requestHeaders
@@ -684,11 +685,11 @@ func (l *LegacyProvider) convert() (Providers, error) {
684685 ClientSecretFile: l.ClientSecretFile,
685686 Type: ProviderType(l.ProviderType),
686687 CAFiles: l.ProviderCAFiles,
687− UseSystemTrustStore: l.UseSystemTrustStore,
688+ UseSystemTrustStore: &l.UseSystemTrustStore,
688689 LoginURL: l.LoginURL,
689690 RedeemURL: l.RedeemURL,
690691 ProfileURL: l.ProfileURL,
691− SkipClaimsFromProfileURL: l.SkipClaimsFromProfileURL,
692+ SkipClaimsFromProfileURL: &l.SkipClaimsFromProfileURL,
692693 ProtectedResource: l.ProtectedResource,
693694 ValidateURL: l.ValidateURL,
694695 Scope: l.Scope,
@@ -701,10 +702,10 @@ func (l *LegacyProvider) convert() (Providers, error) {
701702 // This part is out of the switch section for all providers that support OIDC
702703 provider.OIDCConfig = OIDCOptions{
703704 IssuerURL: l.OIDCIssuerURL,
704− InsecureAllowUnverifiedEmail: l.InsecureOIDCAllowUnverifiedEmail,
705− InsecureSkipIssuerVerification: l.InsecureOIDCSkipIssuerVerification,
706− InsecureSkipNonce: l.InsecureOIDCSkipNonce,
707− SkipDiscovery: l.SkipOIDCDiscovery,
705+ InsecureAllowUnverifiedEmail: &l.InsecureOIDCAllowUnverifiedEmail,
706+ InsecureSkipIssuerVerification: &l.InsecureOIDCSkipIssuerVerification,
707+ InsecureSkipNonce: &l.InsecureOIDCSkipNonce,
708+ SkipDiscovery: &l.SkipOIDCDiscovery,
708709 JwksURL: l.OIDCJwksURL,
709710 UserIDClaim: l.UserIDClaim,
710711 EmailClaim: l.OIDCEmailClaim,
@@ -772,7 +773,7 @@ func (l *LegacyProvider) convert() (Providers, error) {
772773 Groups: l.GoogleGroups,
773774 AdminEmail: l.GoogleAdminEmail,
774775 ServiceAccountJSON: l.GoogleServiceAccountJSON,
775− UseApplicationDefaultCredentials: l.GoogleUseApplicationDefaultCredentials,
776+ UseApplicationDefaultCredentials: &l.GoogleUseApplicationDefaultCredentials,
776777 TargetPrincipal: l.GoogleTargetPrincipal,
777778 UseOrganizationID: l.GoogleUseOrganizationID,
778779 AdminAPIUserScope: l.GoogleAdminAPIUserScope,
@@ -780,7 +781,7 @@ func (l *LegacyProvider) convert() (Providers, error) {
780781 case "entra-id":
781782 provider.MicrosoftEntraIDConfig = MicrosoftEntraIDOptions{
782783 AllowedTenants: l.EntraIDAllowedTenants,
783− FederatedTokenAuth: l.EntraIDFederatedTokenAuth,
784+ FederatedTokenAuth: &l.EntraIDFederatedTokenAuth,
784785 }
785786 }
786787
pkg/apis/options/legacy_options_test.go+44−44
@@ -3,6 +3,7 @@ package options
33import (
44 "time"
55
6+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
67 . "github.com/onsi/ginkgo/v2"
78 . "github.com/onsi/gomega"
89)
@@ -26,7 +27,6 @@ var _ = Describe("Legacy Options", func() {
2627 legacyOpts.LegacyProvider.ClientID = "oauth-proxy"
2728 legacyOpts.LegacyUpstreams.DisableKeepAlives = false
2829
29− truth := true
3030 staticCode := 204
3131 opts.UpstreamServers = UpstreamConfig{
3232 Upstreams: []Upstream{
@@ -35,35 +35,35 @@ var _ = Describe("Legacy Options", func() {
3535 Path: "/baz",
3636 URI: "http://foo.bar/baz",
3737 FlushInterval: &flushInterval,
38− InsecureSkipTLSVerify: true,
39− PassHostHeader: &truth,
40− ProxyWebSockets: &truth,
38+ InsecureSkipTLSVerify: ptr.Ptr(true),
39+ PassHostHeader: ptr.Ptr(true),
40+ ProxyWebSockets: ptr.Ptr(true),
4141 Timeout: &timeout,
42− DisableKeepAlives: legacyOpts.LegacyUpstreams.DisableKeepAlives,
42+ DisableKeepAlives: &legacyOpts.LegacyUpstreams.DisableKeepAlives,
4343 },
4444 {
4545 ID: "/bar",
4646 Path: "/bar",
4747 URI: "file:///var/lib/website",
4848 FlushInterval: &flushInterval,
49− InsecureSkipTLSVerify: true,
50− PassHostHeader: &truth,
51− ProxyWebSockets: &truth,
49+ InsecureSkipTLSVerify: ptr.Ptr(true),
50+ PassHostHeader: ptr.Ptr(true),
51+ ProxyWebSockets: ptr.Ptr(true),
5252 Timeout: &timeout,
53− DisableKeepAlives: legacyOpts.LegacyUpstreams.DisableKeepAlives,
53+ DisableKeepAlives: &legacyOpts.LegacyUpstreams.DisableKeepAlives,
5454 },
5555 {
5656 ID: "static://204",
5757 Path: "/",
5858 URI: "",
59− Static: true,
59+ Static: ptr.Ptr(true),
6060 StaticCode: &staticCode,
6161 FlushInterval: nil,
62− InsecureSkipTLSVerify: false,
62+ InsecureSkipTLSVerify: ptr.Ptr(false),
6363 PassHostHeader: nil,
6464 ProxyWebSockets: nil,
6565 Timeout: nil,
66− DisableKeepAlives: legacyOpts.LegacyUpstreams.DisableKeepAlives,
66+ DisableKeepAlives: &legacyOpts.LegacyUpstreams.DisableKeepAlives,
6767 },
6868 },
6969 }
@@ -71,7 +71,7 @@ var _ = Describe("Legacy Options", func() {
7171 opts.InjectRequestHeaders = []Header{
7272 {
7373 Name: "X-Forwarded-Groups",
74− PreserveRequestValue: false,
74+ PreserveRequestValue: ptr.Ptr(false),
7575 Values: []HeaderValue{
7676 {
7777 ClaimSource: &ClaimSource{
@@ -82,7 +82,7 @@ var _ = Describe("Legacy Options", func() {
8282 },
8383 {
8484 Name: "X-Forwarded-User",
85− PreserveRequestValue: false,
85+ PreserveRequestValue: ptr.Ptr(false),
8686 Values: []HeaderValue{
8787 {
8888 ClaimSource: &ClaimSource{
@@ -93,7 +93,7 @@ var _ = Describe("Legacy Options", func() {
9393 },
9494 {
9595 Name: "X-Forwarded-Email",
96− PreserveRequestValue: false,
96+ PreserveRequestValue: ptr.Ptr(false),
9797 Values: []HeaderValue{
9898 {
9999 ClaimSource: &ClaimSource{
@@ -104,7 +104,7 @@ var _ = Describe("Legacy Options", func() {
104104 },
105105 {
106106 Name: "X-Forwarded-Preferred-Username",
107− PreserveRequestValue: false,
107+ PreserveRequestValue: ptr.Ptr(false),
108108 Values: []HeaderValue{
109109 {
110110 ClaimSource: &ClaimSource{
@@ -123,7 +123,7 @@ var _ = Describe("Legacy Options", func() {
123123
124124 opts.Providers[0].ClientID = "oauth-proxy"
125125 opts.Providers[0].ID = "google=oauth-proxy"
126− opts.Providers[0].OIDCConfig.InsecureSkipNonce = true
126+ opts.Providers[0].OIDCConfig.InsecureSkipNonce = ptr.Ptr(true)
127127 opts.Providers[0].OIDCConfig.AudienceClaims = []string{"aud"}
128128 opts.Providers[0].OIDCConfig.ExtraAudiences = []string{}
129129 opts.Providers[0].LoginURLParameters = []LoginURLParameter{
@@ -157,12 +157,12 @@ var _ = Describe("Legacy Options", func() {
157157 ID: "/baz",
158158 Path: "/baz",
159159 URI: validHTTP,
160− InsecureSkipTLSVerify: skipVerify,
160+ InsecureSkipTLSVerify: &skipVerify,
161161 PassHostHeader: &passHostHeader,
162162 ProxyWebSockets: &proxyWebSockets,
163163 FlushInterval: &flushInterval,
164164 Timeout: &timeout,
165− DisableKeepAlives: disableKeepAlives,
165+ DisableKeepAlives: &disableKeepAlives,
166166 }
167167
168168 // Test cases and expected outcomes
@@ -171,12 +171,12 @@ var _ = Describe("Legacy Options", func() {
171171 ID: "/",
172172 Path: "/",
173173 URI: emptyPathHTTP,
174− InsecureSkipTLSVerify: skipVerify,
174+ InsecureSkipTLSVerify: &skipVerify,
175175 PassHostHeader: &passHostHeader,
176176 ProxyWebSockets: &proxyWebSockets,
177177 FlushInterval: &flushInterval,
178178 Timeout: &timeout,
179− DisableKeepAlives: disableKeepAlives,
179+ DisableKeepAlives: &disableKeepAlives,
180180 }
181181
182182 validFileWithFragment := "file:///var/lib/website#/bar"
@@ -184,12 +184,12 @@ var _ = Describe("Legacy Options", func() {
184184 ID: "/bar",
185185 Path: "/bar",
186186 URI: "file:///var/lib/website",
187− InsecureSkipTLSVerify: skipVerify,
187+ InsecureSkipTLSVerify: &skipVerify,
188188 PassHostHeader: &passHostHeader,
189189 ProxyWebSockets: &proxyWebSockets,
190190 FlushInterval: &flushInterval,
191191 Timeout: &timeout,
192− DisableKeepAlives: disableKeepAlives,
192+ DisableKeepAlives: &disableKeepAlives,
193193 }
194194
195195 validStatic := "static://204"
@@ -198,14 +198,14 @@ var _ = Describe("Legacy Options", func() {
198198 ID: validStatic,
199199 Path: "/",
200200 URI: "",
201− Static: true,
201+ Static: ptr.Ptr(true),
202202 StaticCode: &validStaticCode,
203− InsecureSkipTLSVerify: false,
203+ InsecureSkipTLSVerify: ptr.Ptr(false),
204204 PassHostHeader: nil,
205205 ProxyWebSockets: nil,
206206 FlushInterval: nil,
207207 Timeout: nil,
208− DisableKeepAlives: false,
208+ DisableKeepAlives: ptr.Ptr(false),
209209 }
210210
211211 invalidStatic := "static://abc"
@@ -214,14 +214,14 @@ var _ = Describe("Legacy Options", func() {
214214 ID: invalidStatic,
215215 Path: "/",
216216 URI: "",
217− Static: true,
217+ Static: ptr.Ptr(true),
218218 StaticCode: &invalidStaticCode,
219− InsecureSkipTLSVerify: false,
219+ InsecureSkipTLSVerify: ptr.Ptr(false),
220220 PassHostHeader: nil,
221221 ProxyWebSockets: nil,
222222 FlushInterval: nil,
223223 Timeout: nil,
224− DisableKeepAlives: false,
224+ DisableKeepAlives: ptr.Ptr(false),
225225 }
226226
227227 invalidHTTP := ":foo"
@@ -308,13 +308,13 @@ var _ = Describe("Legacy Options", func() {
308308 }
309309
310310 withPreserveRequestValue := func(h Header, preserve bool) Header {
311− h.PreserveRequestValue = preserve
311+ h.PreserveRequestValue = &preserve
312312 return h
313313 }
314314
315315 xForwardedUser := Header{
316316 Name: "X-Forwarded-User",
317− PreserveRequestValue: false,
317+ PreserveRequestValue: ptr.Ptr(false),
318318 Values: []HeaderValue{
319319 {
320320 ClaimSource: &ClaimSource{
@@ -326,7 +326,7 @@ var _ = Describe("Legacy Options", func() {
326326
327327 xForwardedEmail := Header{
328328 Name: "X-Forwarded-Email",
329− PreserveRequestValue: false,
329+ PreserveRequestValue: ptr.Ptr(false),
330330 Values: []HeaderValue{
331331 {
332332 ClaimSource: &ClaimSource{
@@ -338,7 +338,7 @@ var _ = Describe("Legacy Options", func() {
338338
339339 xForwardedGroups := Header{
340340 Name: "X-Forwarded-Groups",
341− PreserveRequestValue: false,
341+ PreserveRequestValue: ptr.Ptr(false),
342342 Values: []HeaderValue{
343343 {
344344 ClaimSource: &ClaimSource{
@@ -350,7 +350,7 @@ var _ = Describe("Legacy Options", func() {
350350
351351 xForwardedPreferredUsername := Header{
352352 Name: "X-Forwarded-Preferred-Username",
353− PreserveRequestValue: false,
353+ PreserveRequestValue: ptr.Ptr(false),
354354 Values: []HeaderValue{
355355 {
356356 ClaimSource: &ClaimSource{
@@ -362,7 +362,7 @@ var _ = Describe("Legacy Options", func() {
362362
363363 basicAuthHeader := Header{
364364 Name: "Authorization",
365− PreserveRequestValue: false,
365+ PreserveRequestValue: ptr.Ptr(false),
366366 Values: []HeaderValue{
367367 {
368368 ClaimSource: &ClaimSource{
@@ -378,7 +378,7 @@ var _ = Describe("Legacy Options", func() {
378378
379379 xForwardedUserWithEmail := Header{
380380 Name: "X-Forwarded-User",
381− PreserveRequestValue: false,
381+ PreserveRequestValue: ptr.Ptr(false),
382382 Values: []HeaderValue{
383383 {
384384 ClaimSource: &ClaimSource{
@@ -390,7 +390,7 @@ var _ = Describe("Legacy Options", func() {
390390
391391 xForwardedAccessToken := Header{
392392 Name: "X-Forwarded-Access-Token",
393− PreserveRequestValue: false,
393+ PreserveRequestValue: ptr.Ptr(false),
394394 Values: []HeaderValue{
395395 {
396396 ClaimSource: &ClaimSource{
@@ -402,7 +402,7 @@ var _ = Describe("Legacy Options", func() {
402402
403403 basicAuthHeaderWithEmail := Header{
404404 Name: "Authorization",
405− PreserveRequestValue: false,
405+ PreserveRequestValue: ptr.Ptr(false),
406406 Values: []HeaderValue{
407407 {
408408 ClaimSource: &ClaimSource{
@@ -418,7 +418,7 @@ var _ = Describe("Legacy Options", func() {
418418
419419 xAuthRequestUser := Header{
420420 Name: "X-Auth-Request-User",
421− PreserveRequestValue: false,
421+ PreserveRequestValue: ptr.Ptr(false),
422422 Values: []HeaderValue{
423423 {
424424 ClaimSource: &ClaimSource{
@@ -430,7 +430,7 @@ var _ = Describe("Legacy Options", func() {
430430
431431 xAuthRequestEmail := Header{
432432 Name: "X-Auth-Request-Email",
433− PreserveRequestValue: false,
433+ PreserveRequestValue: ptr.Ptr(false),
434434 Values: []HeaderValue{
435435 {
436436 ClaimSource: &ClaimSource{
@@ -442,7 +442,7 @@ var _ = Describe("Legacy Options", func() {
442442
443443 xAuthRequestGroups := Header{
444444 Name: "X-Auth-Request-Groups",
445− PreserveRequestValue: false,
445+ PreserveRequestValue: ptr.Ptr(false),
446446 Values: []HeaderValue{
447447 {
448448 ClaimSource: &ClaimSource{
@@ -454,7 +454,7 @@ var _ = Describe("Legacy Options", func() {
454454
455455 xAuthRequestPreferredUsername := Header{
456456 Name: "X-Auth-Request-Preferred-Username",
457− PreserveRequestValue: false,
457+ PreserveRequestValue: ptr.Ptr(false),
458458 Values: []HeaderValue{
459459 {
460460 ClaimSource: &ClaimSource{
@@ -466,7 +466,7 @@ var _ = Describe("Legacy Options", func() {
466466
467467 xAuthRequestAccessToken := Header{
468468 Name: "X-Auth-Request-Access-Token",
469− PreserveRequestValue: false,
469+ PreserveRequestValue: ptr.Ptr(false),
470470 Values: []HeaderValue{
471471 {
472472 ClaimSource: &ClaimSource{
@@ -478,7 +478,7 @@ var _ = Describe("Legacy Options", func() {
478478
479479 authorizationHeader := Header{
480480 Name: "Authorization",
481− PreserveRequestValue: false,
481+ PreserveRequestValue: ptr.Ptr(false),
482482 Values: []HeaderValue{
483483 {
484484 ClaimSource: &ClaimSource{
pkg/apis/options/providers.go+14−12
@@ -1,5 +1,7 @@
11package options
22
3+import "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
4+
35const (
46 // OIDCEmailClaim is the generic email claim used by the OIDC provider.
57 OIDCEmailClaim = "email"
@@ -67,7 +69,7 @@ type Provider struct {
6769 CAFiles []string `yaml:"caFiles,omitempty"`
6870 // UseSystemTrustStore determines if your custom CA files and the system trust store are used
6971 // If set to true, your custom CA files and the system trust store are used otherwise only your custom CA files.
70− UseSystemTrustStore bool `yaml:"useSystemTrustStore"`
72+ UseSystemTrustStore *bool `yaml:"useSystemTrustStore,omitempty"`
7173 // LoginURL is the authentication endpoint
7274 LoginURL string `yaml:"loginURL,omitempty"`
7375 // LoginURLParameters defines the parameters that can be passed from the start URL to the IdP login URL
@@ -80,7 +82,7 @@ type Provider struct {
8082 ProfileURL string `yaml:"profileURL,omitempty"`
8183 // SkipClaimsFromProfileURL allows to skip request to Profile URL for resolving claims not present in id_token
8284 // default set to 'false'
83− SkipClaimsFromProfileURL bool `yaml:"skipClaimsFromProfileURL"`
85+ SkipClaimsFromProfileURL *bool `yaml:"skipClaimsFromProfileURL,omitempty"`
8486 // ProtectedResource is the resource that is protected (Azure AD and ADFS only)
8587 ProtectedResource string `yaml:"resource,omitempty"`
8688 // ValidateURL is the access token validation endpoint
@@ -181,13 +183,13 @@ type MicrosoftEntraIDOptions struct {
181183
182184 // FederatedTokenAuth enable oAuth2 client authentication with federated token projected
183185 // by Entra Workload Identity plugin, instead of client secret.
184− FederatedTokenAuth bool `yaml:"federatedTokenAuth"`
186+ FederatedTokenAuth *bool `yaml:"federatedTokenAuth,omitempty"`
185187}
186188
187189type ADFSOptions struct {
188190 // Skip adding the scope parameter in login request
189191 // Default value is 'false'
190− SkipScope bool `yaml:"skipScope"`
192+ SkipScope *bool `yaml:"skipScope,omitempty"`
191193}
192194
193195type BitbucketOptions struct {
@@ -227,7 +229,7 @@ type GoogleOptions struct {
227229 // ServiceAccountJSON is the path to the service account json credentials
228230 ServiceAccountJSON string `yaml:"serviceAccountJson,omitempty"`
229231 // UseApplicationDefaultCredentials is a boolean whether to use Application Default Credentials instead of a ServiceAccountJSON
230− UseApplicationDefaultCredentials bool `yaml:"useApplicationDefaultCredentials"`
232+ UseApplicationDefaultCredentials *bool `yaml:"useApplicationDefaultCredentials,omitempty"`
231233 // TargetPrincipal is the Google Service Account used for Application Default Credentials
232234 TargetPrincipal string `yaml:"targetPrincipal,omitempty"`
233235 // UseOrganizationId indicates whether to use the organization ID as the UserName claim
@@ -242,19 +244,19 @@ type OIDCOptions struct {
242244 IssuerURL string `yaml:"issuerURL,omitempty"`
243245 // InsecureAllowUnverifiedEmail prevents failures if an email address in an id_token is not verified
244246 // default set to 'false'
245− InsecureAllowUnverifiedEmail bool `yaml:"insecureAllowUnverifiedEmail"`
247+ InsecureAllowUnverifiedEmail *bool `yaml:"insecureAllowUnverifiedEmail,omitempty"`
246248 // InsecureSkipIssuerVerification skips verification of ID token issuers. When false, ID Token Issuers must match the OIDC discovery URL
247249 // default set to 'false'
248− InsecureSkipIssuerVerification bool `yaml:"insecureSkipIssuerVerification"`
250+ InsecureSkipIssuerVerification *bool `yaml:"insecureSkipIssuerVerification,omitempty"`
249251 // InsecureSkipNonce skips verifying the ID Token's nonce claim that must match
250252 // the random nonce sent in the initial OAuth flow. Otherwise, the nonce is checked
251253 // after the initial OAuth redeem & subsequent token refreshes.
252254 // default set to 'true'
253255 // Warning: In a future release, this will change to 'false' by default for enhanced security.
254− InsecureSkipNonce bool `yaml:"insecureSkipNonce"`
256+ InsecureSkipNonce *bool `yaml:"insecureSkipNonce,omitempty"`
255257 // SkipDiscovery allows to skip OIDC discovery and use manually supplied Endpoints
256258 // default set to 'false'
257− SkipDiscovery bool `yaml:"skipDiscovery"`
259+ SkipDiscovery *bool `yaml:"skipDiscovery,omitempty"`
258260 // JwksURL is the OpenID Connect JWKS URL
259261 // eg: https://www.googleapis.com/oauth2/v3/certs
260262 JwksURL string `yaml:"jwksURL,omitempty"`
@@ -295,9 +297,9 @@ func providerDefaults() Providers {
295297 Tenant: "common",
296298 },
297299 OIDCConfig: OIDCOptions{
298− InsecureAllowUnverifiedEmail: false,
299− InsecureSkipNonce: true,
300− SkipDiscovery: false,
300+ InsecureAllowUnverifiedEmail: ptr.Ptr(false),
301+ InsecureSkipNonce: ptr.Ptr(true),
302+ SkipDiscovery: ptr.Ptr(false),
301303 UserIDClaim: OIDCEmailClaim, // Deprecated: Use OIDCEmailClaim
302304 EmailClaim: OIDCEmailClaim,
303305 GroupsClaim: OIDCGroupsClaim,
pkg/apis/options/upstreams.go+6−6
@@ -14,7 +14,7 @@ const (
1414type UpstreamConfig struct {
1515 // ProxyRawPath will pass the raw url path to upstream allowing for urls
1616 // like: "/%2F/" which would otherwise be redirected to "/"
17− ProxyRawPath bool `yaml:"proxyRawPath"`
17+ ProxyRawPath *bool `yaml:"proxyRawPath,omitempty"`
1818
1919 // Upstreams represents the configuration for the upstream servers.
2020 // Requests will be proxied to this upstream if the path matches the request path.
@@ -64,13 +64,13 @@ type Upstream struct {
6464 // This option is insecure and will allow potential Man-In-The-Middle attacks
6565 // between OAuth2 Proxy and the upstream server.
6666 // Defaults to false.
67− InsecureSkipTLSVerify bool `yaml:"insecureSkipTLSVerify"`
67+ InsecureSkipTLSVerify *bool `yaml:"insecureSkipTLSVerify,omitempty"`
6868
6969 // Static will make all requests to this upstream have a static response.
7070 // The response will have a body of "Authenticated" and a response code
7171 // matching StaticCode.
7272 // If StaticCode is not set, the response will return a 200 response.
73− Static bool `yaml:"static"`
73+ Static *bool `yaml:"static,omitempty"`
7474
7575 // StaticCode determines the response code for the Static response.
7676 // This option can only be used with Static enabled.
@@ -84,11 +84,11 @@ type Upstream struct {
8484 // PassHostHeader determines whether the request host header should be proxied
8585 // to the upstream server.
8686 // Defaults to true.
87− PassHostHeader *bool `yaml:"passHostHeader"`
87+ PassHostHeader *bool `yaml:"passHostHeader,omitempty"`
8888
8989 // ProxyWebSockets enables proxying of websockets to upstream servers
9090 // Defaults to true.
91− ProxyWebSockets *bool `yaml:"proxyWebSockets"`
91+ ProxyWebSockets *bool `yaml:"proxyWebSockets,omitempty"`
9292
9393 // Timeout is the maximum duration the server will wait for a response from the upstream server.
9494 // Defaults to 30 seconds.
@@ -96,5 +96,5 @@ type Upstream struct {
9696
9797 // DisableKeepAlives disables HTTP keep-alive connections to the upstream server.
9898 // Defaults to false.
99− DisableKeepAlives bool `yaml:"disableKeepAlives,omitempty"`
99+ DisableKeepAlives *bool `yaml:"disableKeepAlives,omitempty"`
100100}
pkg/middleware/headers.go+1−1
@@ -27,7 +27,7 @@ func NewRequestHeaderInjector(headers []options.Header) (alice.Constructor, erro
2727func newStripHeaders(headers []options.Header) alice.Constructor {
2828 headersToStrip := []options.Header{}
2929 for _, header := range headers {
30− if !header.PreserveRequestValue {
30+ if !(*header.PreserveRequestValue) {
3131 headersToStrip = append(headersToStrip, header)
3232 }
3333 }
pkg/middleware/headers_test.go+5−4
@@ -8,6 +8,7 @@ import (
88 middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
99 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
1010 sessionsapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
11+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
1112 . "github.com/onsi/ginkgo/v2"
1213 . "github.com/onsi/gomega"
1314)
@@ -115,7 +116,7 @@ var _ = Describe("Headers Suite", func() {
115116 headers: []options.Header{
116117 {
117118 Name: "Claim",
118− PreserveRequestValue: true,
119+ PreserveRequestValue: ptr.Ptr(true),
119120 Values: []options.HeaderValue{
120121 {
121122 ClaimSource: &options.ClaimSource{
@@ -160,7 +161,7 @@ var _ = Describe("Headers Suite", func() {
160161 headers: []options.Header{
161162 {
162163 Name: "Claim",
163− PreserveRequestValue: true,
164+ PreserveRequestValue: ptr.Ptr(true),
164165 Values: []options.HeaderValue{
165166 {
166167 ClaimSource: &options.ClaimSource{
@@ -385,7 +386,7 @@ var _ = Describe("Headers Suite", func() {
385386 headers: []options.Header{
386387 {
387388 Name: "Claim",
388− PreserveRequestValue: true,
389+ PreserveRequestValue: ptr.Ptr(true),
389390 Values: []options.HeaderValue{
390391 {
391392 ClaimSource: &options.ClaimSource{
@@ -432,7 +433,7 @@ var _ = Describe("Headers Suite", func() {
432433 headers: []options.Header{
433434 {
434435 Name: "Claim",
435− PreserveRequestValue: true,
436+ PreserveRequestValue: ptr.Ptr(true),
436437 Values: []options.HeaderValue{
437438 {
438439 ClaimSource: &options.ClaimSource{
pkg/upstream/http.go+3−3
@@ -54,7 +54,7 @@ func newHTTPUpstreamProxy(upstream options.Upstream, u *url.URL, sigData *option
5454 // Set up a WebSocket proxy if required
5555 var wsProxy http.Handler
5656 if upstream.ProxyWebSockets == nil || *upstream.ProxyWebSockets {
57− wsProxy = newWebSocketReverseProxy(u, upstream.InsecureSkipTLSVerify)
57+ wsProxy = newWebSocketReverseProxy(u, *upstream.InsecureSkipTLSVerify)
5858 }
5959
6060 var auth hmacauth.HmacAuth
@@ -149,7 +149,7 @@ func newReverseProxy(target *url.URL, upstream options.Upstream, errorHandler Pr
149149
150150 // InsecureSkipVerify is a configurable option we allow
151151 /* #nosec G402 */
152− if upstream.InsecureSkipTLSVerify {
152+ if *upstream.InsecureSkipTLSVerify {
153153 transport.TLSClientConfig.InsecureSkipVerify = true
154154 }
155155
@@ -168,7 +168,7 @@ func newReverseProxy(target *url.URL, upstream options.Upstream, errorHandler Pr
168168
169169 // Pass on DisableKeepAlives to the transport settings
170170 // to allow for disabling HTTP keep-alive connections
171− transport.DisableKeepAlives = upstream.DisableKeepAlives
171+ transport.DisableKeepAlives = *upstream.DisableKeepAlives
172172
173173 // Apply the customized transport to our proxy before returning it
174174 proxy.Transport = transport
pkg/upstream/http_test.go+11−12
@@ -15,6 +15,7 @@ import (
1515 middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
1616 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
1717 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/middleware"
18+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
1819 . "github.com/onsi/ginkgo/v2"
1920 . "github.com/onsi/gomega"
2021 "golang.org/x/net/websocket"
@@ -23,8 +24,6 @@ import (
2324var _ = Describe("HTTP Upstream Suite", func() {
2425 defaultFlushInterval := options.DefaultUpstreamFlushInterval
2526 defaultTimeout := options.DefaultUpstreamTimeout
26− truth := true
27− falsum := false
2827
2928 type httpUpstreamTableInput struct {
3029 id string
@@ -64,8 +63,8 @@ var _ = Describe("HTTP Upstream Suite", func() {
6463 upstream := options.Upstream{
6564 ID: in.id,
6665 PassHostHeader: &in.passUpstreamHostHeader,
67− ProxyWebSockets: &falsum,
68− InsecureSkipTLSVerify: false,
66+ ProxyWebSockets: ptr.Ptr(false),
67+ InsecureSkipTLSVerify: ptr.Ptr(false),
6968 FlushInterval: &flush,
7069 Timeout: &timeout,
7170 }
@@ -343,9 +342,9 @@ var _ = Describe("HTTP Upstream Suite", func() {
343342
344343 upstream := options.Upstream{
345344 ID: "noPassHost",
346− PassHostHeader: &falsum,
347− ProxyWebSockets: &falsum,
348− InsecureSkipTLSVerify: false,
345+ PassHostHeader: ptr.Ptr(false),
346+ ProxyWebSockets: ptr.Ptr(false),
347+ InsecureSkipTLSVerify: ptr.Ptr(false),
349348 FlushInterval: &defaultFlushInterval,
350349 Timeout: &defaultTimeout,
351350 }
@@ -389,10 +388,10 @@ var _ = Describe("HTTP Upstream Suite", func() {
389388 upstream := options.Upstream{
390389 ID: "foo123",
391390 FlushInterval: &in.flushInterval,
392− InsecureSkipTLSVerify: in.skipVerify,
391+ InsecureSkipTLSVerify: &in.skipVerify,
393392 ProxyWebSockets: &in.proxyWebSockets,
394393 Timeout: &in.timeout,
395− DisableKeepAlives: in.disableKeepAlives,
394+ DisableKeepAlives: &in.disableKeepAlives,
396395 }
397396
398397 handler := newHTTPUpstreamProxy(upstream, u, in.sigData, in.errorHandler)
@@ -487,9 +486,9 @@ var _ = Describe("HTTP Upstream Suite", func() {
487486 timeout := options.DefaultUpstreamTimeout
488487 upstream := options.Upstream{
489488 ID: "websocketProxy",
490− PassHostHeader: &truth,
491− ProxyWebSockets: &truth,
492− InsecureSkipTLSVerify: false,
489+ PassHostHeader: ptr.Ptr(true),
490+ ProxyWebSockets: ptr.Ptr(true),
491+ InsecureSkipTLSVerify: ptr.Ptr(false),
493492 FlushInterval: &flush,
494493 Timeout: &timeout,
495494 }
pkg/upstream/proxy.go+2−2
@@ -27,12 +27,12 @@ func NewProxy(upstreams options.UpstreamConfig, sigData *options.SignatureData,
2727 serveMux: mux.NewRouter(),
2828 }
2929
30− if upstreams.ProxyRawPath {
30+ if *upstreams.ProxyRawPath {
3131 m.serveMux.UseEncodedPath()
3232 }
3333
3434 for _, upstream := range sortByPathLongest(upstreams.Upstreams) {
35− if upstream.Static {
35+ if *upstream.Static {
3636 if err := m.registerStaticResponseHandler(upstream, writer); err != nil {
3737 return nil, fmt.Errorf("could not register static upstream %q: %v", upstream.ID, err)
3838 }
pkg/upstream/proxy_test.go+6−5
@@ -10,6 +10,7 @@ import (
1010 middlewareapi "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/middleware"
1111 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
1212 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/app/pagewriter"
13+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
1314 . "github.com/onsi/ginkgo/v2"
1415 . "github.com/onsi/gomega"
1516)
@@ -60,19 +61,19 @@ var _ = Describe("Proxy Suite", func() {
6061 {
6162 ID: "static-backend",
6263 Path: "/static/",
63− Static: true,
64+ Static: ptr.Ptr(true),
6465 StaticCode: &ok,
6566 },
6667 {
6768 ID: "static-backend-no-trailing-slash",
6869 Path: "/static",
69− Static: true,
70+ Static: ptr.Ptr(true),
7071 StaticCode: &accepted,
7172 },
7273 {
7374 ID: "static-backend-long",
7475 Path: "/static/long",
75− Static: true,
76+ Static: ptr.Ptr(true),
7677 StaticCode: &accepted,
7778 },
7879 {
@@ -83,7 +84,7 @@ var _ = Describe("Proxy Suite", func() {
8384 {
8485 ID: "single-path-backend",
8586 Path: "/single-path",
86− Static: true,
87+ Static: ptr.Ptr(true),
8788 StaticCode: &ok,
8889 },
8990 {
@@ -346,7 +347,7 @@ var _ = Describe("Proxy Suite", func() {
346347 upstream: "",
347348 }),
348349 Entry("containing an escaped '/' with ProxyRawPath", &proxyTableInput{
349− upstreams: options.UpstreamConfig{ProxyRawPath: true},
350+ upstreams: options.UpstreamConfig{ProxyRawPath: ptr.Ptr(true)},
350351 target: "http://example.localhost/%2F/test1/%2F/test2",
351352 response: testHTTPResponse{
352353 code: 404,
pkg/util/ptr/ptr.gonew file+14
@@ -0,0 +1,14 @@
1+package ptr
2+
3+// Ptr generically returns a pointer to the given value.
4+func Ptr[T any](v T) *T {
5+ return &v
6+}
7+
8+// Deref returns the value of the pointer or def(ault) if nil.
9+func Deref[T any](p *T, def T) T {
10+ if p == nil {
11+ return def
12+ }
13+ return *p
14+}
pkg/util/ptr/ptr_test.gonew file+38
@@ -0,0 +1,38 @@
1+package ptr
2+
3+import (
4+ "testing"
5+
6+ "github.com/stretchr/testify/assert"
7+)
8+
9+func TestPtr(t *testing.T) {
10+ p := Ptr(42)
11+ assert.NotNil(t, p)
12+ assert.Equal(t, 42, *p)
13+
14+ s := Ptr("hello")
15+ assert.NotNil(t, s)
16+ assert.Equal(t, "hello", *s)
17+
18+ b := Ptr(true)
19+ assert.NotNil(t, b)
20+ assert.True(t, *b)
21+}
22+
23+func TestDeref(t *testing.T) {
24+ v := Deref(Ptr(99), 0)
25+ assert.Equal(t, 99, v)
26+
27+ v = Deref[int](nil, 123)
28+ assert.Equal(t, 123, v)
29+
30+ s := Deref[string](nil, "default")
31+ assert.Equal(t, "default", s)
32+
33+ b := Deref(Ptr(true), false)
34+ assert.True(t, b)
35+
36+ b = Deref[bool](nil, false)
37+ assert.False(t, b)
38+}
pkg/validation/options.go+1−1
@@ -34,7 +34,7 @@ func Validate(o *options.Options) error {
3434 transport := requests.DefaultTransport.(*http.Transport)
3535 transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} // #nosec G402 -- InsecureSkipVerify is a configurable option we allow
3636 } else if len(o.Providers[0].CAFiles) > 0 {
37− pool, err := util.GetCertPool(o.Providers[0].CAFiles, o.Providers[0].UseSystemTrustStore)
37+ pool, err := util.GetCertPool(o.Providers[0].CAFiles, *o.Providers[0].UseSystemTrustStore)
3838 if err == nil {
3939 transport := requests.DefaultTransport.(*http.Transport)
4040 transport.TLSClientConfig = &tls.Config{
pkg/validation/options_test.go+3−2
@@ -9,6 +9,7 @@ import (
99 "time"
1010
1111 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
12+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
1213 "github.com/stretchr/testify/assert"
1314)
1415
@@ -68,7 +69,7 @@ func TestGoogleGroupOptionsWithoutServiceAccountJSON(t *testing.T) {
6869
6970func TestGoogleGroupOptionsWithoutAdminEmail(t *testing.T) {
7071 o := testOptions()
71− o.Providers[0].GoogleConfig.UseApplicationDefaultCredentials = true
72+ o.Providers[0].GoogleConfig.UseApplicationDefaultCredentials = ptr.Ptr(true)
7273 err := Validate(o)
7374 assert.NotEqual(t, nil, err)
7475
@@ -81,7 +82,7 @@ func TestGoogleGroupOptionsWithoutGroups(t *testing.T) {
8182 o := testOptions()
8283 // Set admin email and application default credentials but no groups - should still require them
8384 o.Providers[0].GoogleConfig.AdminEmail = "admin@example.com"
84− o.Providers[0].GoogleConfig.UseApplicationDefaultCredentials = true
85+ o.Providers[0].GoogleConfig.UseApplicationDefaultCredentials = ptr.Ptr(true)
8586 err := Validate(o)
8687 // Should pass validation since google-group is now optional
8788 assert.Equal(t, nil, err)
pkg/validation/providers.go+4−3
@@ -5,6 +5,7 @@ import (
55 "os"
66
77 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
8+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
89)
910
1011// validateProviders is the initial validation migration for multiple providrers
@@ -64,7 +65,7 @@ func validateProvider(provider options.Provider, providerIDs map[string]struct{}
6465// providerRequiresClientSecret checks if provider requires client secret to be set
6566// or it can be omitted in favor of JWT token to authenticate oAuth client
6667func providerRequiresClientSecret(provider options.Provider) bool {
67− if provider.Type == "entra-id" && provider.MicrosoftEntraIDConfig.FederatedTokenAuth {
68+ if provider.Type == "entra-id" && *provider.MicrosoftEntraIDConfig.FederatedTokenAuth {
6869 return false
6970 }
7071
@@ -96,7 +97,7 @@ func validateGoogleConfig(provider options.Provider) []string {
9697
9798 hasAdminEmail := provider.GoogleConfig.AdminEmail != ""
9899 hasSAJSON := provider.GoogleConfig.ServiceAccountJSON != ""
99− useADC := provider.GoogleConfig.UseApplicationDefaultCredentials
100+ useADC := ptr.Deref(provider.GoogleConfig.UseApplicationDefaultCredentials, false)
100101
101102 if !hasAdminEmail && !hasSAJSON && !useADC {
102103 return msgs
@@ -123,7 +124,7 @@ func validateGoogleConfig(provider options.Provider) []string {
123124func validateEntraConfig(provider options.Provider) []string {
124125 msgs := []string{}
125126
126− if provider.MicrosoftEntraIDConfig.FederatedTokenAuth {
127+ if *provider.MicrosoftEntraIDConfig.FederatedTokenAuth {
127128 federatedTokenPath := os.Getenv("AZURE_FEDERATED_TOKEN_FILE")
128129
129130 if federatedTokenPath == "" {
pkg/validation/upstreams.go+5−5
@@ -54,19 +54,19 @@ func validateUpstream(upstream options.Upstream, ids, paths map[string]struct{})
5454func validateStaticUpstream(upstream options.Upstream) []string {
5555 msgs := []string{}
5656
57− if !upstream.Static && upstream.StaticCode != nil {
57+ if !*upstream.Static && upstream.StaticCode != nil {
5858 msgs = append(msgs, fmt.Sprintf("upstream %q has staticCode (%d), but is not a static upstream, set 'static' for a static response", upstream.ID, *upstream.StaticCode))
5959 }
6060
6161 // Checks after this only make sense when the upstream is static
62− if !upstream.Static {
62+ if !*upstream.Static {
6363 return msgs
6464 }
6565
6666 if upstream.URI != "" {
6767 msgs = append(msgs, fmt.Sprintf("upstream %q has uri, but is a static upstream, this will have no effect.", upstream.ID))
6868 }
69− if upstream.InsecureSkipTLSVerify {
69+ if *upstream.InsecureSkipTLSVerify {
7070 msgs = append(msgs, fmt.Sprintf("upstream %q has insecureSkipTLSVerify, but is a static upstream, this will have no effect.", upstream.ID))
7171 }
7272 if upstream.FlushInterval != nil && *upstream.FlushInterval != options.DefaultUpstreamFlushInterval {
@@ -85,13 +85,13 @@ func validateStaticUpstream(upstream options.Upstream) []string {
8585func validateUpstreamURI(upstream options.Upstream) []string {
8686 msgs := []string{}
8787
88− if !upstream.Static && upstream.URI == "" {
88+ if !*upstream.Static && upstream.URI == "" {
8989 msgs = append(msgs, fmt.Sprintf("upstream %q has empty uri: uris are required for all non-static upstreams", upstream.ID))
9090 return msgs
9191 }
9292
9393 // Checks after this only make sense the upstream is not static
94− if upstream.Static {
94+ if *upstream.Static {
9595 return msgs
9696 }
9797
pkg/validation/upstreams_test.go+6−6
@@ -4,6 +4,7 @@ import (
44 "time"
55
66 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
7+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
78 . "github.com/onsi/ginkgo/v2"
89 . "github.com/onsi/gomega"
910)
@@ -16,7 +17,6 @@ var _ = Describe("Upstreams", func() {
1617
1718 flushInterval := 5 * time.Second
1819 staticCode200 := 200
19− truth := true
2020
2121 validHTTPUpstream := options.Upstream{
2222 ID: "validHTTPUpstream",
@@ -26,7 +26,7 @@ var _ = Describe("Upstreams", func() {
2626 validStaticUpstream := options.Upstream{
2727 ID: "validStaticUpstream",
2828 Path: "/validStaticUpstream",
29− Static: true,
29+ Static: ptr.Ptr(true),
3030 }
3131 validFileUpstream := options.Upstream{
3232 ID: "validFileUpstream",
@@ -145,11 +145,11 @@ var _ = Describe("Upstreams", func() {
145145 ID: "foo",
146146 Path: "/foo",
147147 URI: "ftp://foo",
148− Static: true,
148+ Static: ptr.Ptr(true),
149149 FlushInterval: &flushInterval,
150− PassHostHeader: &truth,
151− ProxyWebSockets: &truth,
152− InsecureSkipTLSVerify: true,
150+ PassHostHeader: ptr.Ptr(true),
151+ ProxyWebSockets: ptr.Ptr(true),
152+ InsecureSkipTLSVerify: ptr.Ptr(true),
153153 },
154154 },
155155 },
providers/adfs.go+1−1
@@ -50,7 +50,7 @@ func NewADFSProvider(p *ProviderData, opts options.Provider) *ADFSProvider {
5050
5151 return &ADFSProvider{
5252 OIDCProvider: oidcProvider,
53− skipScope: opts.ADFSConfig.SkipScope,
53+ skipScope: *opts.ADFSConfig.SkipScope,
5454 oidcEnrichFunc: oidcProvider.EnrichSession,
5555 oidcRefreshFunc: oidcProvider.RefreshSession,
5656 }
providers/adfs_test.go+2−1
@@ -16,6 +16,7 @@ import (
1616 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
1717 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
1818 internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc"
19+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
1920 . "github.com/onsi/ginkgo/v2"
2021 . "github.com/onsi/gomega"
2122)
@@ -172,7 +173,7 @@ var _ = Describe("ADFS Provider Tests", func() {
172173 ProtectedResource: resource,
173174 Scope: "",
174175 }, options.Provider{
175− ADFSConfig: options.ADFSOptions{SkipScope: true},
176+ ADFSConfig: options.ADFSOptions{SkipScope: ptr.Ptr(true)},
176177 })
177178
178179 result := p.GetLoginURL("https://example.com/adfs/oauth2/", "", "", url.Values{})
providers/google.go+3−2
@@ -108,7 +108,8 @@ func NewGoogleProvider(p *ProviderData, opts options.GoogleOptions) (*GoogleProv
108108 },
109109 }
110110
111− if opts.UseOrganizationID || opts.ServiceAccountJSON != "" || opts.UseApplicationDefaultCredentials {
111+ if opts.UseOrganizationID || opts.ServiceAccountJSON != "" || *opts.UseApplicationDefaultCredentials {
112+ provider.configureGroups(opts)
112113
113114 // reuse admin service to avoid multiple calls for token
114115 var adminService *admin.Service
@@ -304,7 +305,7 @@ var possibleScopesList = [...]string{
304305}
305306
306307func getOauth2TokenSource(ctx context.Context, opts options.GoogleOptions, scope string) oauth2.TokenSource {
307− if opts.UseApplicationDefaultCredentials {
308+ if *opts.UseApplicationDefaultCredentials {
308309 ts, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{
309310 TargetPrincipal: getTargetPrincipal(ctx, opts),
310311 Scopes: strings.Split(scope, " "),
providers/ms_entra_id.go+1−1
@@ -51,7 +51,7 @@ func NewMicrosoftEntraIDProvider(p *ProviderData, opts options.Provider) *Micros
5151 OIDCProvider: NewOIDCProvider(p, opts.OIDCConfig),
5252
5353 multiTenantAllowedTenants: opts.MicrosoftEntraIDConfig.AllowedTenants,
54− federatedTokenAuth: opts.MicrosoftEntraIDConfig.FederatedTokenAuth,
54+ federatedTokenAuth: *opts.MicrosoftEntraIDConfig.FederatedTokenAuth,
5555 microsoftGraphURL: microsoftGraphURL,
5656 }
5757}
providers/ms_entra_id_test.go+4−3
@@ -13,6 +13,7 @@ import (
1313 "github.com/coreos/go-oidc/v3/oidc"
1414 "github.com/golang-jwt/jwt/v5"
1515 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
16+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
1617 "github.com/stretchr/testify/assert"
1718
1819 . "github.com/onsi/gomega"
@@ -24,7 +25,7 @@ func TestAzureEntraOIDCProviderNewMultiTenant(t *testing.T) {
2425 provider := NewMicrosoftEntraIDProvider(&ProviderData{},
2526 options.Provider{OIDCConfig: options.OIDCOptions{
2627 IssuerURL: "https://login.microsoftonline.com/common/v2.0",
27− InsecureSkipIssuerVerification: true,
28+ InsecureSkipIssuerVerification: ptr.Ptr(true),
2829 }},
2930 )
3031 g.Expect(provider.Data().ProviderName).To(Equal("Microsoft Entra ID"))
@@ -90,8 +91,8 @@ func TestAzureEntraOIDCProviderValidateSessionAllowedTenants(t *testing.T) {
9091 options.Provider{
9192 OIDCConfig: options.OIDCOptions{
9293 IssuerURL: "https://login.microsoftonline.com/common/v2.0",
93− InsecureSkipIssuerVerification: true,
94− InsecureSkipNonce: true,
94+ InsecureSkipIssuerVerification: ptr.Ptr(true),
95+ InsecureSkipNonce: ptr.Ptr(true),
9596 },
9697 MicrosoftEntraIDConfig: options.MicrosoftEntraIDOptions{
9798 AllowedTenants: []string{"85d7d600-7804-4d92-8d43-9c33c21c130c"},
providers/oidc.go+1−1
@@ -50,7 +50,7 @@ func NewOIDCProvider(p *ProviderData, opts options.OIDCOptions) *OIDCProvider {
5050
5151 return &OIDCProvider{
5252 ProviderData: p,
53− SkipNonce: opts.InsecureSkipNonce,
53+ SkipNonce: *opts.InsecureSkipNonce,
5454 }
5555}
5656
providers/oidc_test.go+1−1
@@ -63,7 +63,7 @@ func newOIDCProvider(serverURL *url.URL, skipNonce bool) *OIDCProvider {
6363 }
6464
6565 p := NewOIDCProvider(providerData, options.OIDCOptions{
66− InsecureSkipNonce: skipNonce,
66+ InsecureSkipNonce: &skipNonce,
6767 })
6868
6969 return p
providers/providers.go+4−4
@@ -98,8 +98,8 @@ func newProviderDataFromConfig(providerConfig options.Provider) (*ProviderData,
9898 IssuerURL: providerConfig.OIDCConfig.IssuerURL,
9999 JWKsURL: providerConfig.OIDCConfig.JwksURL,
100100 PublicKeyFiles: providerConfig.OIDCConfig.PublicKeyFiles,
101− SkipDiscovery: providerConfig.OIDCConfig.SkipDiscovery,
102− SkipIssuerVerification: providerConfig.OIDCConfig.InsecureSkipIssuerVerification,
101+ SkipDiscovery: *providerConfig.OIDCConfig.SkipDiscovery,
102+ SkipIssuerVerification: *providerConfig.OIDCConfig.InsecureSkipIssuerVerification,
103103 })
104104 if err != nil {
105105 return nil, fmt.Errorf("error building OIDC ProviderVerifier: %v", err)
@@ -143,10 +143,10 @@ func newProviderDataFromConfig(providerConfig options.Provider) (*ProviderData,
143143 }
144144
145145 // Make the OIDC options available to all providers that support it
146− p.AllowUnverifiedEmail = providerConfig.OIDCConfig.InsecureAllowUnverifiedEmail
146+ p.AllowUnverifiedEmail = *providerConfig.OIDCConfig.InsecureAllowUnverifiedEmail
147147 p.EmailClaim = providerConfig.OIDCConfig.EmailClaim
148148 p.GroupsClaim = providerConfig.OIDCConfig.GroupsClaim
149− p.SkipClaimsFromProfileURL = providerConfig.SkipClaimsFromProfileURL
149+ p.SkipClaimsFromProfileURL = *providerConfig.SkipClaimsFromProfileURL
150150
151151 // Set PKCE enabled or disabled based on discovery and force options
152152 p.CodeChallengeMethod = parseCodeChallengeMethod(providerConfig)
providers/providers_test.go+5−4
@@ -5,6 +5,7 @@ import (
55 "testing"
66
77 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
8+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util/ptr"
89 . "github.com/onsi/gomega"
910)
1011
@@ -81,7 +82,7 @@ func TestSkipOIDCDiscovery(t *testing.T) {
8182 ClientSecretFile: clientSecret,
8283 OIDCConfig: options.OIDCOptions{
8384 IssuerURL: msIssuerURL,
84− SkipDiscovery: true,
85+ SkipDiscovery: ptr.Ptr(true),
8586 },
8687 }
8788
@@ -108,7 +109,7 @@ func TestURLsCorrectlyParsed(t *testing.T) {
108109 RedeemURL: msTokenURL,
109110 OIDCConfig: options.OIDCOptions{
110111 IssuerURL: msIssuerURL,
111− SkipDiscovery: true,
112+ SkipDiscovery: ptr.Ptr(true),
112113 JwksURL: msKeysURL,
113114 },
114115 }
@@ -216,7 +217,7 @@ func TestScope(t *testing.T) {
216217 AllowedGroups: tc.allowedGroups,
217218 OIDCConfig: options.OIDCOptions{
218219 IssuerURL: msIssuerURL,
219− SkipDiscovery: true,
220+ SkipDiscovery: ptr.Ptr(true),
220221 JwksURL: msKeysURL,
221222 },
222223 }
@@ -297,7 +298,7 @@ func TestEmailClaimCorrectlySet(t *testing.T) {
297298 RedeemURL: msTokenURL,
298299 OIDCConfig: options.OIDCOptions{
299300 IssuerURL: msIssuerURL,
300− SkipDiscovery: true,
301+ SkipDiscovery: ptr.Ptr(true),
301302 JwksURL: msKeysURL,
302303 UserIDClaim: tc.userIDClaim,
303304 EmailClaim: tc.emailClaim,