git.iko.soy/typeable/oauth2-proxy
on master help sign in
Integrate new header injectors with OAuth2 Proxy
commit8059a812cdd88024eb37d2df6e0aed6cf5a118ca authorJoel Speed <joel.speed@hotmail.co.uk> dateWed 29 Jul 2020, 20:10 (6 years ago) parentd26c65b
7 files changed+484−550
main.go+1−29 oauthproxy.go+68−160 oauthproxy_test.go+318−301 pkg/validation/options.go−8 pkg/validation/options_test.go−23 pkg/validation/sessions.go+14−11 pkg/validation/sessions_test.go+83−18
main.go+1−29
@@ -3,17 +3,14 @@ package main
33import (
44 "fmt"
55 "math/rand"
6− "net"
76 "os"
87 "os/signal"
98 "runtime"
109 "syscall"
1110 "time"
1211
13− "github.com/justinas/alice"
1412 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
1513 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
16− "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/middleware"
1714 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/validation"
1815)
1916
@@ -63,33 +60,8 @@ func main() {
6360
6461 rand.Seed(time.Now().UnixNano())
6562
66− chain := alice.New()
67−
68− if opts.ForceHTTPS {
69− _, httpsPort, err := net.SplitHostPort(opts.HTTPSAddress)
70− if err != nil {
71− logger.Fatalf("FATAL: invalid HTTPS address %q: %v", opts.HTTPAddress, err)
72− }
73− chain = chain.Append(middleware.NewRedirectToHTTPS(httpsPort))
74− }
75−
76− healthCheckPaths := []string{opts.PingPath}
77− healthCheckUserAgents := []string{opts.PingUserAgent}
78− if opts.GCPHealthChecks {
79− healthCheckPaths = append(healthCheckPaths, "/liveness_check", "/readiness_check")
80− healthCheckUserAgents = append(healthCheckUserAgents, "GoogleHC/1.0")
81− }
82−
83− // To silence logging of health checks, register the health check handler before
84− // the logging handler
85− if opts.Logging.SilencePing {
86− chain = chain.Append(middleware.NewHealthCheck(healthCheckPaths, healthCheckUserAgents), LoggingHandler)
87− } else {
88− chain = chain.Append(LoggingHandler, middleware.NewHealthCheck(healthCheckPaths, healthCheckUserAgents))
89− }
90−
9163 s := &Server{
92− Handler: chain.Then(oauthproxy),
64+ Handler: oauthproxy,
9365 Opts: opts,
9466 stop: make(chan struct{}, 1),
9567 }
oauthproxy.go+68−160
@@ -2,7 +2,6 @@ package main
22
33import (
44 "context"
5− b64 "encoding/base64"
65 "encoding/json"
76 "errors"
87 "fmt"
@@ -98,7 +97,6 @@ type OAuthProxy struct {
9897 PassAuthorization bool
9998 PreferEmailToUser bool
10099 skipAuthPreflight bool
101− skipAuthStripHeaders bool
102100 skipJwtBearerTokens bool
103101 mainJwtBearerVerifier *oidc.IDTokenVerifier
104102 extraJwtBearerVerifiers []*oidc.IDTokenVerifier
@@ -110,6 +108,8 @@ type OAuthProxy struct {
110108 AllowedGroups []string
111109
112110 sessionChain alice.Chain
111+ headersChain alice.Chain
112+ preAuthChain alice.Chain
113113}
114114
115115// NewOAuthProxy creates a new instance of OAuthProxy from the options provided
@@ -169,7 +169,15 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
169169 return nil, err
170170 }
171171
172+ preAuthChain, err := buildPreAuthChain(opts)
173+ if err != nil {
174+ return nil, fmt.Errorf("could not build pre-auth chain: %v", err)
175+ }
172176 sessionChain := buildSessionChain(opts, sessionStore, basicAuthValidator)
177+ headersChain, err := buildHeadersChain(opts)
178+ if err != nil {
179+ return nil, fmt.Errorf("could not build headers chain: %v", err)
180+ }
173181
174182 return &OAuthProxy{
175183 CookieName: opts.Cookie.Name,
@@ -201,20 +209,10 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
201209 allowedRoutes: allowedRoutes,
202210 whitelistDomains: opts.WhitelistDomains,
203211 skipAuthPreflight: opts.SkipAuthPreflight,
204− skipAuthStripHeaders: opts.SkipAuthStripHeaders,
205212 skipJwtBearerTokens: opts.SkipJwtBearerTokens,
206213 mainJwtBearerVerifier: opts.GetOIDCVerifier(),
207214 extraJwtBearerVerifiers: opts.GetJWTBearerVerifiers(),
208215 realClientIPParser: opts.GetRealClientIPParser(),
209− SetXAuthRequest: opts.SetXAuthRequest,
210− PassBasicAuth: opts.PassBasicAuth,
211− SetBasicAuth: opts.SetBasicAuth,
212− PassUserHeaders: opts.PassUserHeaders,
213− BasicAuthPassword: opts.BasicAuthPassword,
214− PassAccessToken: opts.PassAccessToken,
215− SetAuthorization: opts.SetAuthorization,
216− PassAuthorization: opts.PassAuthorization,
217− PreferEmailToUser: opts.PreferEmailToUser,
218216 SkipProviderButton: opts.SkipProviderButton,
219217 templates: templates,
220218 trustedIPs: trustedIPs,
@@ -226,12 +224,46 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
226224 basicAuthValidator: basicAuthValidator,
227225 displayHtpasswdForm: basicAuthValidator != nil,
228226 sessionChain: sessionChain,
227+ headersChain: headersChain,
228+ preAuthChain: preAuthChain,
229229 }, nil
230230}
231231
232−func buildSessionChain(opts *options.Options, sessionStore sessionsapi.SessionStore, validator basic.Validator) alice.Chain {
232+// buildPreAuthChain constructs a chain that should process every request before
233+// the OAuth2 Proxy authentication logic kicks in.
234+// For example forcing HTTPS or health checks.
235+func buildPreAuthChain(opts *options.Options) (alice.Chain, error) {
233236 chain := alice.New(middleware.NewScope())
234237
238+ if opts.ForceHTTPS {
239+ _, httpsPort, err := net.SplitHostPort(opts.HTTPSAddress)
240+ if err != nil {
241+ return alice.Chain{}, fmt.Errorf("invalid HTTPS address %q: %v", opts.HTTPAddress, err)
242+ }
243+ chain = chain.Append(middleware.NewRedirectToHTTPS(httpsPort))
244+ }
245+
246+ healthCheckPaths := []string{opts.PingPath}
247+ healthCheckUserAgents := []string{opts.PingUserAgent}
248+ if opts.GCPHealthChecks {
249+ healthCheckPaths = append(healthCheckPaths, "/liveness_check", "/readiness_check")
250+ healthCheckUserAgents = append(healthCheckUserAgents, "GoogleHC/1.0")
251+ }
252+
253+ // To silence logging of health checks, register the health check handler before
254+ // the logging handler
255+ if opts.Logging.SilencePing {
256+ chain = chain.Append(middleware.NewHealthCheck(healthCheckPaths, healthCheckUserAgents), LoggingHandler)
257+ } else {
258+ chain = chain.Append(LoggingHandler, middleware.NewHealthCheck(healthCheckPaths, healthCheckUserAgents))
259+ }
260+
261+ return chain, nil
262+}
263+
264+func buildSessionChain(opts *options.Options, sessionStore sessionsapi.SessionStore, validator basic.Validator) alice.Chain {
265+ chain := alice.New()
266+
235267 if opts.SkipJwtBearerTokens {
236268 sessionLoaders := []middlewareapi.TokenToSessionLoader{}
237269 if opts.GetOIDCVerifier() != nil {
@@ -264,6 +296,20 @@ func buildSessionChain(opts *options.Options, sessionStore sessionsapi.SessionSt
264296 return chain
265297}
266298
299+func buildHeadersChain(opts *options.Options) (alice.Chain, error) {
300+ requestInjector, err := middleware.NewRequestHeaderInjector(opts.InjectRequestHeaders)
301+ if err != nil {
302+ return alice.Chain{}, fmt.Errorf("error constructing request header injector: %v", err)
303+ }
304+
305+ responseInjector, err := middleware.NewResponseHeaderInjector(opts.InjectResponseHeaders)
306+ if err != nil {
307+ return alice.Chain{}, fmt.Errorf("error constructing request header injector: %v", err)
308+ }
309+
310+ return alice.New(requestInjector, responseInjector), nil
311+}
312+
267313func buildSignInMessage(opts *options.Options) string {
268314 var msg string
269315 if len(opts.Banner) >= 1 {
@@ -685,6 +731,10 @@ func (p *OAuthProxy) IsTrustedIP(req *http.Request) bool {
685731}
686732
687733func (p *OAuthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
734+ p.preAuthChain.Then(http.HandlerFunc(p.serveHTTP)).ServeHTTP(rw, req)
735+}
736+
737+func (p *OAuthProxy) serveHTTP(rw http.ResponseWriter, req *http.Request) {
688738 if req.URL.Path != p.AuthOnlyPath && strings.HasPrefix(req.URL.Path, p.ProxyPrefix) {
689739 prepareNoCache(rw)
690740 }
@@ -884,15 +934,14 @@ func (p *OAuthProxy) AuthenticateOnly(rw http.ResponseWriter, req *http.Request)
884934
885935 // we are authenticated
886936 p.addHeadersForProxying(rw, req, session)
887− rw.WriteHeader(http.StatusAccepted)
937+ p.headersChain.Then(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
938+ rw.WriteHeader(http.StatusAccepted)
939+ })).ServeHTTP(rw, req)
888940}
889941
890942// SkipAuthProxy proxies allowlisted requests and skips authentication
891943func (p *OAuthProxy) SkipAuthProxy(rw http.ResponseWriter, req *http.Request) {
892− if p.skipAuthStripHeaders {
893− p.stripAuthHeaders(req)
894− }
895− p.serveMux.ServeHTTP(rw, req)
944+ p.headersChain.Then(p.serveMux).ServeHTTP(rw, req)
896945}
897946
898947// Proxy proxies the user request if the user is authenticated else it prompts
@@ -903,8 +952,7 @@ func (p *OAuthProxy) Proxy(rw http.ResponseWriter, req *http.Request) {
903952 case nil:
904953 // we are authenticated
905954 p.addHeadersForProxying(rw, req, session)
906− p.serveMux.ServeHTTP(rw, req)
907−
955+ p.headersChain.Then(p.serveMux).ServeHTTP(rw, req)
908956 case ErrNeedsLogin:
909957 // we need to send the user to a login screen
910958 if isAjax(req) {
@@ -961,120 +1009,6 @@ func (p *OAuthProxy) getAuthenticatedSession(rw http.ResponseWriter, req *http.R
9611009
9621010// addHeadersForProxying adds the appropriate headers the request / response for proxying
9631011func (p *OAuthProxy) addHeadersForProxying(rw http.ResponseWriter, req *http.Request, session *sessionsapi.SessionState) {
964− if p.PassBasicAuth {
965− if p.PreferEmailToUser && session.Email != "" {
966− req.SetBasicAuth(session.Email, p.BasicAuthPassword)
967− req.Header["X-Forwarded-User"] = []string{session.Email}
968− req.Header.Del("X-Forwarded-Email")
969− } else {
970− req.SetBasicAuth(session.User, p.BasicAuthPassword)
971− req.Header["X-Forwarded-User"] = []string{session.User}
972− if session.Email != "" {
973− req.Header["X-Forwarded-Email"] = []string{session.Email}
974− } else {
975− req.Header.Del("X-Forwarded-Email")
976− }
977− }
978− if session.PreferredUsername != "" {
979− req.Header["X-Forwarded-Preferred-Username"] = []string{session.PreferredUsername}
980− } else {
981− req.Header.Del("X-Forwarded-Preferred-Username")
982− }
983− }
984−
985− if p.PassUserHeaders {
986− if p.PreferEmailToUser && session.Email != "" {
987− req.Header["X-Forwarded-User"] = []string{session.Email}
988− req.Header.Del("X-Forwarded-Email")
989− } else {
990− req.Header["X-Forwarded-User"] = []string{session.User}
991− if session.Email != "" {
992− req.Header["X-Forwarded-Email"] = []string{session.Email}
993− } else {
994− req.Header.Del("X-Forwarded-Email")
995− }
996− }
997−
998− if session.PreferredUsername != "" {
999− req.Header["X-Forwarded-Preferred-Username"] = []string{session.PreferredUsername}
1000− } else {
1001− req.Header.Del("X-Forwarded-Preferred-Username")
1002− }
1003−
1004− if len(session.Groups) > 0 {
1005− for _, group := range session.Groups {
1006− req.Header.Add("X-Forwarded-Groups", group)
1007− }
1008− } else {
1009− req.Header.Del("X-Forwarded-Groups")
1010− }
1011− }
1012−
1013− if p.SetXAuthRequest {
1014− rw.Header().Set("X-Auth-Request-User", session.User)
1015− if session.Email != "" {
1016− rw.Header().Set("X-Auth-Request-Email", session.Email)
1017− } else {
1018− rw.Header().Del("X-Auth-Request-Email")
1019− }
1020− if session.PreferredUsername != "" {
1021− rw.Header().Set("X-Auth-Request-Preferred-Username", session.PreferredUsername)
1022− } else {
1023− rw.Header().Del("X-Auth-Request-Preferred-Username")
1024− }
1025−
1026− if p.PassAccessToken {
1027− if session.AccessToken != "" {
1028− rw.Header().Set("X-Auth-Request-Access-Token", session.AccessToken)
1029− } else {
1030− rw.Header().Del("X-Auth-Request-Access-Token")
1031− }
1032− }
1033−
1034− if len(session.Groups) > 0 {
1035− for _, group := range session.Groups {
1036− rw.Header().Add("X-Auth-Request-Groups", group)
1037− }
1038− } else {
1039− rw.Header().Del("X-Auth-Request-Groups")
1040− }
1041− }
1042−
1043− if p.PassAccessToken {
1044− if session.AccessToken != "" {
1045− req.Header["X-Forwarded-Access-Token"] = []string{session.AccessToken}
1046− } else {
1047− req.Header.Del("X-Forwarded-Access-Token")
1048− }
1049− }
1050−
1051− if p.PassAuthorization {
1052− if session.IDToken != "" {
1053− req.Header["Authorization"] = []string{fmt.Sprintf("Bearer %s", session.IDToken)}
1054− } else {
1055− req.Header.Del("Authorization")
1056− }
1057− }
1058− if p.SetBasicAuth {
1059− switch {
1060− case p.PreferEmailToUser && session.Email != "":
1061− authVal := b64.StdEncoding.EncodeToString([]byte(session.Email + ":" + p.BasicAuthPassword))
1062− rw.Header().Set("Authorization", "Basic "+authVal)
1063− case session.User != "":
1064− authVal := b64.StdEncoding.EncodeToString([]byte(session.User + ":" + p.BasicAuthPassword))
1065− rw.Header().Set("Authorization", "Basic "+authVal)
1066− default:
1067− rw.Header().Del("Authorization")
1068− }
1069− }
1070− if p.SetAuthorization {
1071− if session.IDToken != "" {
1072− rw.Header().Set("Authorization", fmt.Sprintf("Bearer %s", session.IDToken))
1073− } else {
1074− rw.Header().Del("Authorization")
1075− }
1076− }
1077−
10781012 if session.Email == "" {
10791013 rw.Header().Set("GAP-Auth", session.User)
10801014 } else {
@@ -1082,32 +1016,6 @@ func (p *OAuthProxy) addHeadersForProxying(rw http.ResponseWriter, req *http.Req
10821016 }
10831017}
10841018
1085−// stripAuthHeaders removes Auth headers for allowlisted routes from skipAuthRegex
1086−func (p *OAuthProxy) stripAuthHeaders(req *http.Request) {
1087− if p.PassBasicAuth {
1088− req.Header.Del("X-Forwarded-User")
1089− req.Header.Del("X-Forwarded-Groups")
1090− req.Header.Del("X-Forwarded-Email")
1091− req.Header.Del("X-Forwarded-Preferred-Username")
1092− req.Header.Del("Authorization")
1093− }
1094−
1095− if p.PassUserHeaders {
1096− req.Header.Del("X-Forwarded-User")
1097− req.Header.Del("X-Forwarded-Groups")
1098− req.Header.Del("X-Forwarded-Email")
1099− req.Header.Del("X-Forwarded-Preferred-Username")
1100− }
1101−
1102− if p.PassAccessToken {
1103− req.Header.Del("X-Forwarded-Access-Token")
1104− }
1105−
1106− if p.PassAuthorization {
1107− req.Header.Del("Authorization")
1108− }
1109−}
1110−
11111019// isAjax checks if a request is an ajax request
11121020func isAjax(req *http.Request) bool {
11131021 acceptValues := req.Header.Values("Accept")
oauthproxy_test.go+318−301
@@ -495,6 +495,8 @@ func TestBasicAuthPassword(t *testing.T) {
495495 t.Fatal(err)
496496 }
497497 }))
498+
499+ basicAuthPassword := "This is a secure password"
498500 opts := baseTestOptions()
499501 opts.UpstreamServers = options.Upstreams{
500502 {
@@ -505,11 +507,22 @@ func TestBasicAuthPassword(t *testing.T) {
505507 }
506508
507509 opts.Cookie.Secure = false
508− opts.PassBasicAuth = true
509− opts.SetBasicAuth = true
510− opts.PassUserHeaders = true
511− opts.PreferEmailToUser = true
512− opts.BasicAuthPassword = "This is a secure password"
510+ opts.InjectRequestHeaders = []options.Header{
511+ {
512+ Name: "Authorization",
513+ Values: []options.HeaderValue{
514+ {
515+ ClaimSource: &options.ClaimSource{
516+ Claim: "email",
517+ BasicAuthPassword: &options.SecretSource{
518+ Value: []byte(base64.StdEncoding.EncodeToString([]byte(basicAuthPassword))),
519+ },
520+ },
521+ },
522+ },
523+ },
524+ }
525+
513526 err := validation.Validate(opts)
514527 assert.NoError(t, err)
515528
@@ -524,148 +537,44 @@ func TestBasicAuthPassword(t *testing.T) {
524537 t.Fatal(err)
525538 }
526539
540+ // Save the required session
527541 rw := httptest.NewRecorder()
528− req, _ := http.NewRequest("GET", "/oauth2/callback?code=callback_code&state=nonce:", strings.NewReader(""))
529− req.AddCookie(proxy.MakeCSRFCookie(req, "nonce", proxy.CookieExpire, time.Now()))
530− proxy.ServeHTTP(rw, req)
531− if rw.Code >= 400 {
532− t.Fatalf("expected 3xx got %d", rw.Code)
533− }
534− cookie := rw.Header().Values("Set-Cookie")[1]
535−
536− cookieName := proxy.CookieName
537− var value string
538− keyPrefix := cookieName + "="
539−
540− for _, field := range strings.Split(cookie, "; ") {
541− value = strings.TrimPrefix(field, keyPrefix)
542− if value != field {
543− break
544− } else {
545− value = ""
546− }
547− }
548−
549− req, _ = http.NewRequest("GET", "/", strings.NewReader(""))
550− req.AddCookie(&http.Cookie{
551− Name: cookieName,
552− Value: value,
553− Path: "/",
554− Expires: time.Now().Add(time.Duration(24)),
555− HttpOnly: true,
542+ req, _ := http.NewRequest("GET", "/", nil)
543+ err = proxy.sessionStore.Save(rw, req, &sessions.SessionState{
544+ Email: emailAddress,
556545 })
557− req.AddCookie(proxy.MakeCSRFCookie(req, "nonce", proxy.CookieExpire, time.Now()))
546+ assert.NoError(t, err)
558547
548+ // Extract the cookie value to inject into the test request
549+ cookie := rw.Header().Values("Set-Cookie")[0]
550+
551+ req, _ = http.NewRequest("GET", "/", nil)
552+ req.Header.Set("Cookie", cookie)
559553 rw = httptest.NewRecorder()
560554 proxy.ServeHTTP(rw, req)
561555
562556 // The username in the basic auth credentials is expected to be equal to the email address from the
563557 // auth response, so we use the same variable here.
564− expectedHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte(emailAddress+":"+opts.BasicAuthPassword))
558+ expectedHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte(emailAddress+":"+basicAuthPassword))
565559 assert.Equal(t, expectedHeader, rw.Body.String())
566560 providerServer.Close()
567561}
568562
569−func TestBasicAuthWithEmail(t *testing.T) {
570− opts := baseTestOptions()
571− opts.PassBasicAuth = true
572− opts.PassUserHeaders = false
573− opts.PreferEmailToUser = false
574− opts.BasicAuthPassword = "This is a secure password"
575− err := validation.Validate(opts)
576− assert.NoError(t, err)
577−
578− const emailAddress = "john.doe@example.com"
579− const userName = "9fcab5c9b889a557"
580−
581− // The username in the basic auth credentials is expected to be equal to the email address from the
582− expectedEmailHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte(emailAddress+":"+opts.BasicAuthPassword))
583− expectedUserHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte(userName+":"+opts.BasicAuthPassword))
584−
585− created := time.Now()
586− session := &sessions.SessionState{
587− User: userName,
588− Email: emailAddress,
589− AccessToken: "oauth_token",
590− CreatedAt: &created,
591− }
592− {
593− rw := httptest.NewRecorder()
594− req, _ := http.NewRequest("GET", opts.ProxyPrefix+"/testCase0", nil)
595− proxy, err := NewOAuthProxy(opts, func(email string) bool {
596− return email == emailAddress
597− })
598− if err != nil {
599− t.Fatal(err)
600− }
601− proxy.addHeadersForProxying(rw, req, session)
602− assert.Equal(t, expectedUserHeader, req.Header["Authorization"][0])
603− assert.Equal(t, userName, req.Header["X-Forwarded-User"][0])
604− }
605−
606− opts.PreferEmailToUser = true
607− {
608− rw := httptest.NewRecorder()
609− req, _ := http.NewRequest("GET", opts.ProxyPrefix+"/testCase1", nil)
610−
611− proxy, err := NewOAuthProxy(opts, func(email string) bool {
612− return email == emailAddress
613− })
614− if err != nil {
615− t.Fatal(err)
616− }
617− proxy.addHeadersForProxying(rw, req, session)
618− assert.Equal(t, expectedEmailHeader, req.Header["Authorization"][0])
619− assert.Equal(t, emailAddress, req.Header["X-Forwarded-User"][0])
620− }
621−}
622−
623−func TestPassUserHeadersWithEmail(t *testing.T) {
563+func TestPassGroupsHeadersWithGroups(t *testing.T) {
624564 opts := baseTestOptions()
625− err := validation.Validate(opts)
626− assert.NoError(t, err)
627−
628− const emailAddress = "john.doe@example.com"
629− const userName = "9fcab5c9b889a557"
630−
631− created := time.Now()
632− session := &sessions.SessionState{
633− User: userName,
634− Email: emailAddress,
635− AccessToken: "oauth_token",
636− CreatedAt: &created,
637− }
638− {
639− rw := httptest.NewRecorder()
640− req, _ := http.NewRequest("GET", opts.ProxyPrefix+"/testCase0", nil)
641− proxy, err := NewOAuthProxy(opts, func(email string) bool {
642− return email == emailAddress
643− })
644− if err != nil {
645− t.Fatal(err)
646− }
647− proxy.addHeadersForProxying(rw, req, session)
648− assert.Equal(t, userName, req.Header["X-Forwarded-User"][0])
649− }
650−
651− opts.PreferEmailToUser = true
652− {
653− rw := httptest.NewRecorder()
654− req, _ := http.NewRequest("GET", opts.ProxyPrefix+"/testCase1", nil)
655−
656− proxy, err := NewOAuthProxy(opts, func(email string) bool {
657− return email == emailAddress
658− })
659− if err != nil {
660− t.Fatal(err)
661− }
662− proxy.addHeadersForProxying(rw, req, session)
663− assert.Equal(t, emailAddress, req.Header["X-Forwarded-User"][0])
565+ opts.InjectRequestHeaders = []options.Header{
566+ {
567+ Name: "X-Forwarded-Groups",
568+ Values: []options.HeaderValue{
569+ {
570+ ClaimSource: &options.ClaimSource{
571+ Claim: "groups",
572+ },
573+ },
574+ },
575+ },
664576 }
665−}
666577
667−func TestPassGroupsHeadersWithGroups(t *testing.T) {
668− opts := baseTestOptions()
669578 err := validation.Validate(opts)
670579 assert.NoError(t, err)
671580
@@ -681,161 +590,27 @@ func TestPassGroupsHeadersWithGroups(t *testing.T) {
681590 AccessToken: "oauth_token",
682591 CreatedAt: &created,
683592 }
684− {
685− rw := httptest.NewRecorder()
686− req, _ := http.NewRequest("GET", opts.ProxyPrefix+"/testCase0", nil)
687− proxy, err := NewOAuthProxy(opts, func(email string) bool {
688− return email == emailAddress
689− })
690− if err != nil {
691− t.Fatal(err)
692− }
693− proxy.addHeadersForProxying(rw, req, session)
694− assert.Equal(t, groups, req.Header["X-Forwarded-Groups"])
695− }
696−}
697−
698−func TestStripAuthHeaders(t *testing.T) {
699− testCases := map[string]struct {
700− SkipAuthStripHeaders bool
701− PassBasicAuth bool
702− PassUserHeaders bool
703− PassAccessToken bool
704− PassAuthorization bool
705− StrippedHeaders map[string]bool
706− }{
707− "Default options": {
708− SkipAuthStripHeaders: true,
709− PassBasicAuth: true,
710− PassUserHeaders: true,
711− PassAccessToken: false,
712− PassAuthorization: false,
713− StrippedHeaders: map[string]bool{
714− "X-Forwarded-User": true,
715− "X-Forwared-Groups": true,
716− "X-Forwarded-Email": true,
717− "X-Forwarded-Preferred-Username": true,
718− "X-Forwarded-Access-Token": false,
719− "Authorization": true,
720− },
721− },
722− "Pass access token": {
723− SkipAuthStripHeaders: true,
724− PassBasicAuth: true,
725− PassUserHeaders: true,
726− PassAccessToken: true,
727− PassAuthorization: false,
728− StrippedHeaders: map[string]bool{
729− "X-Forwarded-User": true,
730− "X-Forwared-Groups": true,
731− "X-Forwarded-Email": true,
732− "X-Forwarded-Preferred-Username": true,
733− "X-Forwarded-Access-Token": true,
734− "Authorization": true,
735− },
736− },
737− "Nothing setting Authorization": {
738− SkipAuthStripHeaders: true,
739− PassBasicAuth: false,
740− PassUserHeaders: true,
741− PassAccessToken: true,
742− PassAuthorization: false,
743− StrippedHeaders: map[string]bool{
744− "X-Forwarded-User": true,
745− "X-Forwared-Groups": true,
746− "X-Forwarded-Email": true,
747− "X-Forwarded-Preferred-Username": true,
748− "X-Forwarded-Access-Token": true,
749− "Authorization": false,
750− },
751− },
752− "Only Authorization header modified": {
753− SkipAuthStripHeaders: true,
754− PassBasicAuth: false,
755− PassUserHeaders: false,
756− PassAccessToken: false,
757− PassAuthorization: true,
758− StrippedHeaders: map[string]bool{
759− "X-Forwarded-User": false,
760− "X-Forwared-Groups": false,
761− "X-Forwarded-Email": false,
762− "X-Forwarded-Preferred-Username": false,
763− "X-Forwarded-Access-Token": false,
764− "Authorization": true,
765− },
766− },
767− "Don't strip any headers (default options)": {
768− SkipAuthStripHeaders: false,
769− PassBasicAuth: true,
770− PassUserHeaders: true,
771− PassAccessToken: false,
772− PassAuthorization: false,
773− StrippedHeaders: map[string]bool{
774− "X-Forwarded-User": false,
775− "X-Forwared-Groups": false,
776− "X-Forwarded-Email": false,
777− "X-Forwarded-Preferred-Username": false,
778− "X-Forwarded-Access-Token": false,
779− "Authorization": false,
780− },
781− },
782− "Don't strip any headers (custom options)": {
783− SkipAuthStripHeaders: false,
784− PassBasicAuth: true,
785− PassUserHeaders: true,
786− PassAccessToken: true,
787− PassAuthorization: false,
788− StrippedHeaders: map[string]bool{
789− "X-Forwarded-User": false,
790− "X-Forwared-Groups": false,
791− "X-Forwarded-Email": false,
792− "X-Forwarded-Preferred-Username": false,
793− "X-Forwarded-Access-Token": false,
794− "Authorization": false,
795− },
796− },
797− }
798593
799− initialHeaders := map[string]string{
800− "X-Forwarded-User": "9fcab5c9b889a557",
801− "X-Forwarded-Email": "john.doe@example.com",
802− "X-Forwarded-Groups": "a,b,c",
803− "X-Forwarded-Preferred-Username": "john.doe",
804− "X-Forwarded-Access-Token": "AccessToken",
805− "Authorization": "bearer IDToken",
806− }
594+ proxy, err := NewOAuthProxy(opts, func(email string) bool {
595+ return email == emailAddress
596+ })
597+ assert.NoError(t, err)
807598
808− for name, tc := range testCases {
809− t.Run(name, func(t *testing.T) {
810− opts := baseTestOptions()
811− opts.SkipAuthStripHeaders = tc.SkipAuthStripHeaders
812− opts.PassBasicAuth = tc.PassBasicAuth
813− opts.PassUserHeaders = tc.PassUserHeaders
814− opts.PassAccessToken = tc.PassAccessToken
815− opts.PassAuthorization = tc.PassAuthorization
816− err := validation.Validate(opts)
817− assert.NoError(t, err)
599+ // Save the required session
600+ rw := httptest.NewRecorder()
601+ req, _ := http.NewRequest("GET", "/", nil)
602+ err = proxy.sessionStore.Save(rw, req, session)
603+ assert.NoError(t, err)
818604
819− req, _ := http.NewRequest("GET", fmt.Sprintf("%s/testCase", opts.ProxyPrefix), nil)
820− for header, val := range initialHeaders {
821− req.Header.Set(header, val)
822− }
605+ // Extract the cookie value to inject into the test request
606+ cookie := rw.Header().Values("Set-Cookie")[0]
823607
824− proxy, err := NewOAuthProxy(opts, func(_ string) bool { return true })
825− assert.NoError(t, err)
826− if proxy.skipAuthStripHeaders {
827− proxy.stripAuthHeaders(req)
828− }
608+ req, _ = http.NewRequest("GET", "/", nil)
609+ req.Header.Set("Cookie", cookie)
610+ rw = httptest.NewRecorder()
611+ proxy.ServeHTTP(rw, req)
829612
830− for header, stripped := range tc.StrippedHeaders {
831− if stripped {
832− assert.Equal(t, req.Header.Get(header), "")
833− } else {
834− assert.Equal(t, req.Header.Get(header), initialHeaders[header])
835− }
836− }
837− })
838− }
613+ assert.Equal(t, groups, req.Header["X-Forwarded-Groups"])
839614}
840615
841616type PassAccessTokenTest struct {
@@ -884,7 +659,21 @@ func NewPassAccessTokenTest(opts PassAccessTokenTestOptions) (*PassAccessTokenTe
884659 }
885660
886661 patt.opts.Cookie.Secure = false
887− patt.opts.PassAccessToken = opts.PassAccessToken
662+ if opts.PassAccessToken {
663+ patt.opts.InjectRequestHeaders = []options.Header{
664+ {
665+ Name: "X-Forwarded-Access-Token",
666+ Values: []options.HeaderValue{
667+ {
668+ ClaimSource: &options.ClaimSource{
669+ Claim: "access_token",
670+ },
671+ },
672+ },
673+ },
674+ }
675+ }
676+
888677 err := validation.Validate(patt.opts)
889678 if err != nil {
890679 return nil, err
@@ -1442,7 +1231,48 @@ func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) {
14421231 var pcTest ProcessCookieTest
14431232
14441233 pcTest.opts = baseTestOptions()
1445− pcTest.opts.SetXAuthRequest = true
1234+ pcTest.opts.InjectResponseHeaders = []options.Header{
1235+ {
1236+ Name: "X-Auth-Request-User",
1237+ Values: []options.HeaderValue{
1238+ {
1239+ ClaimSource: &options.ClaimSource{
1240+ Claim: "user",
1241+ },
1242+ },
1243+ },
1244+ },
1245+ {
1246+ Name: "X-Auth-Request-Email",
1247+ Values: []options.HeaderValue{
1248+ {
1249+ ClaimSource: &options.ClaimSource{
1250+ Claim: "email",
1251+ },
1252+ },
1253+ },
1254+ },
1255+ {
1256+ Name: "X-Auth-Request-Groups",
1257+ Values: []options.HeaderValue{
1258+ {
1259+ ClaimSource: &options.ClaimSource{
1260+ Claim: "groups",
1261+ },
1262+ },
1263+ },
1264+ },
1265+ {
1266+ Name: "X-Forwarded-Preferred-Username",
1267+ Values: []options.HeaderValue{
1268+ {
1269+ ClaimSource: &options.ClaimSource{
1270+ Claim: "preferred_username",
1271+ },
1272+ },
1273+ },
1274+ },
1275+ }
14461276 pcTest.opts.AllowedGroups = []string{"oauth_groups"}
14471277 err := validation.Validate(pcTest.opts)
14481278 assert.NoError(t, err)
@@ -1480,8 +1310,62 @@ func TestAuthOnlyEndpointSetBasicAuthTrueRequestHeaders(t *testing.T) {
14801310 var pcTest ProcessCookieTest
14811311
14821312 pcTest.opts = baseTestOptions()
1483− pcTest.opts.SetXAuthRequest = true
1484− pcTest.opts.SetBasicAuth = true
1313+ pcTest.opts.InjectResponseHeaders = []options.Header{
1314+ {
1315+ Name: "X-Auth-Request-User",
1316+ Values: []options.HeaderValue{
1317+ {
1318+ ClaimSource: &options.ClaimSource{
1319+ Claim: "user",
1320+ },
1321+ },
1322+ },
1323+ },
1324+ {
1325+ Name: "X-Auth-Request-Email",
1326+ Values: []options.HeaderValue{
1327+ {
1328+ ClaimSource: &options.ClaimSource{
1329+ Claim: "email",
1330+ },
1331+ },
1332+ },
1333+ },
1334+ {
1335+ Name: "X-Auth-Request-Groups",
1336+ Values: []options.HeaderValue{
1337+ {
1338+ ClaimSource: &options.ClaimSource{
1339+ Claim: "groups",
1340+ },
1341+ },
1342+ },
1343+ },
1344+ {
1345+ Name: "X-Forwarded-Preferred-Username",
1346+ Values: []options.HeaderValue{
1347+ {
1348+ ClaimSource: &options.ClaimSource{
1349+ Claim: "preferred_username",
1350+ },
1351+ },
1352+ },
1353+ },
1354+ {
1355+ Name: "Authorization",
1356+ Values: []options.HeaderValue{
1357+ {
1358+ ClaimSource: &options.ClaimSource{
1359+ Claim: "user",
1360+ BasicAuthPassword: &options.SecretSource{
1361+ Value: []byte(base64.StdEncoding.EncodeToString([]byte("This is a secure password"))),
1362+ },
1363+ },
1364+ },
1365+ },
1366+ },
1367+ }
1368+
14851369 err := validation.Validate(pcTest.opts)
14861370 assert.NoError(t, err)
14871371
@@ -1511,7 +1395,7 @@ func TestAuthOnlyEndpointSetBasicAuthTrueRequestHeaders(t *testing.T) {
15111395 assert.Equal(t, http.StatusAccepted, pcTest.rw.Code)
15121396 assert.Equal(t, "oauth_user", pcTest.rw.Header().Values("X-Auth-Request-User")[0])
15131397 assert.Equal(t, "oauth_user@example.com", pcTest.rw.Header().Values("X-Auth-Request-Email")[0])
1514− expectedHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte("oauth_user:"+pcTest.opts.BasicAuthPassword))
1398+ expectedHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte("oauth_user:This is a secure password"))
15151399 assert.Equal(t, expectedHeader, pcTest.rw.Header().Values("Authorization")[0])
15161400}
15171401
@@ -1519,8 +1403,48 @@ func TestAuthOnlyEndpointSetBasicAuthFalseRequestHeaders(t *testing.T) {
15191403 var pcTest ProcessCookieTest
15201404
15211405 pcTest.opts = baseTestOptions()
1522− pcTest.opts.SetXAuthRequest = true
1523− pcTest.opts.SetBasicAuth = false
1406+ pcTest.opts.InjectResponseHeaders = []options.Header{
1407+ {
1408+ Name: "X-Auth-Request-User",
1409+ Values: []options.HeaderValue{
1410+ {
1411+ ClaimSource: &options.ClaimSource{
1412+ Claim: "user",
1413+ },
1414+ },
1415+ },
1416+ },
1417+ {
1418+ Name: "X-Auth-Request-Email",
1419+ Values: []options.HeaderValue{
1420+ {
1421+ ClaimSource: &options.ClaimSource{
1422+ Claim: "email",
1423+ },
1424+ },
1425+ },
1426+ },
1427+ {
1428+ Name: "X-Auth-Request-Groups",
1429+ Values: []options.HeaderValue{
1430+ {
1431+ ClaimSource: &options.ClaimSource{
1432+ Claim: "groups",
1433+ },
1434+ },
1435+ },
1436+ },
1437+ {
1438+ Name: "X-Forwarded-Preferred-Username",
1439+ Values: []options.HeaderValue{
1440+ {
1441+ ClaimSource: &options.ClaimSource{
1442+ Claim: "preferred_username",
1443+ },
1444+ },
1445+ },
1446+ },
1447+ }
15241448 err := validation.Validate(pcTest.opts)
15251449 assert.NoError(t, err)
15261450
@@ -1985,9 +1909,74 @@ func TestGetJwtSession(t *testing.T) {
19851909 &oidc.Config{ClientID: "https://test.myapp.com", SkipExpiryCheck: true})
19861910
19871911 test, err := NewAuthOnlyEndpointTest(func(opts *options.Options) {
1988− opts.PassAuthorization = true
1989− opts.SetAuthorization = true
1990− opts.SetXAuthRequest = true
1912+ opts.InjectRequestHeaders = []options.Header{
1913+ {
1914+ Name: "Authorization",
1915+ Values: []options.HeaderValue{
1916+ {
1917+ ClaimSource: &options.ClaimSource{
1918+ Claim: "id_token",
1919+ Prefix: "Bearer ",
1920+ },
1921+ },
1922+ },
1923+ },
1924+ {
1925+ Name: "X-Forwarded-User",
1926+ Values: []options.HeaderValue{
1927+ {
1928+ ClaimSource: &options.ClaimSource{
1929+ Claim: "user",
1930+ },
1931+ },
1932+ },
1933+ },
1934+ {
1935+ Name: "X-Forwarded-Email",
1936+ Values: []options.HeaderValue{
1937+ {
1938+ ClaimSource: &options.ClaimSource{
1939+ Claim: "email",
1940+ },
1941+ },
1942+ },
1943+ },
1944+ }
1945+
1946+ opts.InjectResponseHeaders = []options.Header{
1947+ {
1948+ Name: "Authorization",
1949+ Values: []options.HeaderValue{
1950+ {
1951+ ClaimSource: &options.ClaimSource{
1952+ Claim: "id_token",
1953+ Prefix: "Bearer ",
1954+ },
1955+ },
1956+ },
1957+ },
1958+ {
1959+ Name: "X-Auth-Request-User",
1960+ Values: []options.HeaderValue{
1961+ {
1962+ ClaimSource: &options.ClaimSource{
1963+ Claim: "user",
1964+ },
1965+ },
1966+ },
1967+ },
1968+ {
1969+ Name: "X-Auth-Request-Email",
1970+ Values: []options.HeaderValue{
1971+ {
1972+ ClaimSource: &options.ClaimSource{
1973+ Claim: "email",
1974+ },
1975+ },
1976+ },
1977+ },
1978+ }
1979+
19911980 opts.SkipJwtBearerTokens = true
19921981 opts.SetJWTBearerVerifiers(append(opts.GetJWTBearerVerifiers(), verifier))
19931982 })
@@ -2004,15 +1993,6 @@ func TestGetJwtSession(t *testing.T) {
20041993 "Authorization": {authHeader},
20051994 }
20061995
2007− // Bearer
2008− expires := time.Unix(1912151821, 0)
2009− session, err := test.proxy.getAuthenticatedSession(test.rw, test.req)
2010− assert.NoError(t, err)
2011− assert.Equal(t, session.User, "1234567890")
2012− assert.Equal(t, session.Email, "john@example.com")
2013− assert.Equal(t, session.ExpiresOn, &expires)
2014− assert.Equal(t, session.IDToken, goodJwt)
2015−
20161996 test.proxy.ServeHTTP(test.rw, test.req)
20171997 if test.rw.Code >= 400 {
20181998 t.Fatalf("expected 3xx got %d", test.rw.Code)
@@ -2140,6 +2120,43 @@ func baseTestOptions() *options.Options {
21402120 opts.ClientID = clientID
21412121 opts.ClientSecret = clientSecret
21422122 opts.EmailDomains = []string{"*"}
2123+
2124+ // Default injected headers for legacy configuration
2125+ opts.InjectRequestHeaders = []options.Header{
2126+ {
2127+ Name: "Authorization",
2128+ Values: []options.HeaderValue{
2129+ {
2130+ ClaimSource: &options.ClaimSource{
2131+ Claim: "user",
2132+ BasicAuthPassword: &options.SecretSource{
2133+ Value: []byte(base64.StdEncoding.EncodeToString([]byte("This is a secure password"))),
2134+ },
2135+ },
2136+ },
2137+ },
2138+ },
2139+ {
2140+ Name: "X-Forwarded-User",
2141+ Values: []options.HeaderValue{
2142+ {
2143+ ClaimSource: &options.ClaimSource{
2144+ Claim: "user",
2145+ },
2146+ },
2147+ },
2148+ },
2149+ {
2150+ Name: "X-Forwarded-Email",
2151+ Values: []options.HeaderValue{
2152+ {
2153+ ClaimSource: &options.ClaimSource{
2154+ Claim: "email",
2155+ },
2156+ },
2157+ },
2158+ },
2159+ }
21432160 return opts
21442161}
21452162
pkg/validation/options.go−8
@@ -73,10 +73,6 @@ func Validate(o *options.Options) error {
7373 "\n use email-domain=* to authorize all email addresses")
7474 }
7575
76− if o.SetBasicAuth && o.SetAuthorization {
77− msgs = append(msgs, "mutually exclusive: set-basic-auth and set-authorization-header can not both be true")
78− }
79−
8076 if o.OIDCIssuerURL != "" {
8177
8278 ctx := context.Background()
@@ -161,10 +157,6 @@ func Validate(o *options.Options) error {
161157 }
162158 }
163159
164− if o.PreferEmailToUser && !o.PassBasicAuth && !o.PassUserHeaders {
165− msgs = append(msgs, "PreferEmailToUser should only be used with PassBasicAuth or PassUserHeaders")
166− }
167−
168160 if o.SkipJwtBearerTokens {
169161 // Configure extra issuers
170162 if len(o.ExtraJwtIssuers) > 0 {
pkg/validation/options_test.go−23
@@ -162,29 +162,6 @@ func TestDefaultProviderApiSettings(t *testing.T) {
162162 assert.Equal(t, "profile email", p.Scope)
163163}
164164
165−func TestPassAccessTokenRequiresSpecificCookieSecretLengths(t *testing.T) {
166− o := testOptions()
167− assert.Equal(t, nil, Validate(o))
168−
169− assert.Equal(t, false, o.PassAccessToken)
170− o.PassAccessToken = true
171− o.Cookie.Secret = "cookie of invalid length-"
172− assert.NotEqual(t, nil, Validate(o))
173−
174− o.PassAccessToken = false
175− o.Cookie.Refresh = time.Duration(24) * time.Hour
176− assert.NotEqual(t, nil, Validate(o))
177−
178− o.Cookie.Secret = "16 bytes AES-128"
179− assert.Equal(t, nil, Validate(o))
180−
181− o.Cookie.Secret = "24 byte secret AES-192--"
182− assert.Equal(t, nil, Validate(o))
183−
184− o.Cookie.Secret = "32 byte secret for AES-256------"
185− assert.Equal(t, nil, Validate(o))
186−}
187−
188165func TestCookieRefreshMustBeLessThanCookieExpire(t *testing.T) {
189166 o := testOptions()
190167 assert.Equal(t, nil, Validate(o))
pkg/validation/sessions.go+14−11
@@ -16,18 +16,21 @@ func validateSessionCookieMinimal(o *options.Options) []string {
1616 }
1717
1818 msgs := []string{}
19− if o.PassAuthorization {
20− msgs = append(msgs,
21− "pass_authorization_header requires oauth tokens in sessions. session_cookie_minimal cannot be set")
22− }
23− if o.SetAuthorization {
24− msgs = append(msgs,
25− "set_authorization_header requires oauth tokens in sessions. session_cookie_minimal cannot be set")
26− }
27− if o.PassAccessToken {
28− msgs = append(msgs,
29− "pass_access_token requires oauth tokens in sessions. session_cookie_minimal cannot be set")
19+ for _, header := range append(o.InjectRequestHeaders, o.InjectResponseHeaders...) {
20+ for _, value := range header.Values {
21+ if value.ClaimSource != nil {
22+ if value.ClaimSource.Claim == "access_token" {
23+ msgs = append(msgs,
24+ fmt.Sprintf("access_token claim for header %q requires oauth tokens in sessions. session_cookie_minimal cannot be set", header.Name))
25+ }
26+ if value.ClaimSource.Claim == "id_token" {
27+ msgs = append(msgs,
28+ fmt.Sprintf("id_token claim for header %q requires oauth tokens in sessions. session_cookie_minimal cannot be set", header.Name))
29+ }
30+ }
31+ }
3032 }
33+
3134 if o.Cookie.Refresh != time.Duration(0) {
3235 msgs = append(msgs,
3336 "cookie_refresh > 0 requires oauth tokens in sessions. session_cookie_minimal cannot be set")
pkg/validation/sessions_test.go+83−18
@@ -13,10 +13,9 @@ import (
1313
1414var _ = Describe("Sessions", func() {
1515 const (
16− passAuthorizationMsg = "pass_authorization_header requires oauth tokens in sessions. session_cookie_minimal cannot be set"
17− setAuthorizationMsg = "set_authorization_header requires oauth tokens in sessions. session_cookie_minimal cannot be set"
18− passAccessTokenMsg = "pass_access_token requires oauth tokens in sessions. session_cookie_minimal cannot be set"
19− cookieRefreshMsg = "cookie_refresh > 0 requires oauth tokens in sessions. session_cookie_minimal cannot be set"
16+ idTokenConflictMsg = "id_token claim for header \"X-ID-Token\" requires oauth tokens in sessions. session_cookie_minimal cannot be set"
17+ accessTokenConflictMsg = "access_token claim for header \"X-Access-Token\" requires oauth tokens in sessions. session_cookie_minimal cannot be set"
18+ cookieRefreshMsg = "cookie_refresh > 0 requires oauth tokens in sessions. session_cookie_minimal cannot be set"
2019 )
2120
2221 type cookieMinimalTableInput struct {
@@ -38,14 +37,25 @@ var _ = Describe("Sessions", func() {
3837 },
3938 errStrings: []string{},
4039 }),
41− Entry("No minimal cookie session & passAuthorization", &cookieMinimalTableInput{
40+ Entry("No minimal cookie session & request header has access_token claim", &cookieMinimalTableInput{
4241 opts: &options.Options{
4342 Session: options.SessionOptions{
4443 Cookie: options.CookieStoreOptions{
4544 Minimal: false,
4645 },
4746 },
48− PassAuthorization: true,
47+ InjectRequestHeaders: []options.Header{
48+ {
49+ Name: "X-Access-Token",
50+ Values: []options.HeaderValue{
51+ {
52+ ClaimSource: &options.ClaimSource{
53+ Claim: "access_token",
54+ },
55+ },
56+ },
57+ },
58+ },
4959 },
5060 errStrings: []string{},
5161 }),
@@ -59,38 +69,71 @@ var _ = Describe("Sessions", func() {
5969 },
6070 errStrings: []string{},
6171 }),
62− Entry("PassAuthorization conflict", &cookieMinimalTableInput{
72+ Entry("Request Header id_token conflict", &cookieMinimalTableInput{
6373 opts: &options.Options{
6474 Session: options.SessionOptions{
6575 Cookie: options.CookieStoreOptions{
6676 Minimal: true,
6777 },
6878 },
69− PassAuthorization: true,
79+ InjectRequestHeaders: []options.Header{
80+ {
81+ Name: "X-ID-Token",
82+ Values: []options.HeaderValue{
83+ {
84+ ClaimSource: &options.ClaimSource{
85+ Claim: "id_token",
86+ },
87+ },
88+ },
89+ },
90+ },
7091 },
71− errStrings: []string{passAuthorizationMsg},
92+ errStrings: []string{idTokenConflictMsg},
7293 }),
73− Entry("SetAuthorization conflict", &cookieMinimalTableInput{
94+ Entry("Response Header id_token conflict", &cookieMinimalTableInput{
7495 opts: &options.Options{
7596 Session: options.SessionOptions{
7697 Cookie: options.CookieStoreOptions{
7798 Minimal: true,
7899 },
79100 },
80− SetAuthorization: true,
101+ InjectResponseHeaders: []options.Header{
102+ {
103+ Name: "X-ID-Token",
104+ Values: []options.HeaderValue{
105+ {
106+ ClaimSource: &options.ClaimSource{
107+ Claim: "id_token",
108+ },
109+ },
110+ },
111+ },
112+ },
81113 },
82− errStrings: []string{setAuthorizationMsg},
114+ errStrings: []string{idTokenConflictMsg},
83115 }),
84− Entry("PassAccessToken conflict", &cookieMinimalTableInput{
116+ Entry("Request Header access_token conflict", &cookieMinimalTableInput{
85117 opts: &options.Options{
86118 Session: options.SessionOptions{
87119 Cookie: options.CookieStoreOptions{
88120 Minimal: true,
89121 },
90122 },
91− PassAccessToken: true,
123+ InjectRequestHeaders: []options.Header{
124+ {
125+ Name: "X-Access-Token",
126+ Values: []options.HeaderValue{
127+ {
128+ ClaimSource: &options.ClaimSource{
129+ Claim: "access_token",
130+ },
131+ },
132+ },
133+ },
134+ },
92135 },
93− errStrings: []string{passAccessTokenMsg},
136+ errStrings: []string{accessTokenConflictMsg},
94137 }),
95138 Entry("CookieRefresh conflict", &cookieMinimalTableInput{
96139 opts: &options.Options{
@@ -112,10 +155,32 @@ var _ = Describe("Sessions", func() {
112155 Minimal: true,
113156 },
114157 },
115− PassAuthorization: true,
116− PassAccessToken: true,
158+ InjectResponseHeaders: []options.Header{
159+ {
160+ Name: "X-ID-Token",
161+ Values: []options.HeaderValue{
162+ {
163+ ClaimSource: &options.ClaimSource{
164+ Claim: "id_token",
165+ },
166+ },
167+ },
168+ },
169+ },
170+ InjectRequestHeaders: []options.Header{
171+ {
172+ Name: "X-Access-Token",
173+ Values: []options.HeaderValue{
174+ {
175+ ClaimSource: &options.ClaimSource{
176+ Claim: "access_token",
177+ },
178+ },
179+ },
180+ },
181+ },
117182 },
118− errStrings: []string{passAuthorizationMsg, passAccessTokenMsg},
183+ errStrings: []string{idTokenConflictMsg, accessTokenConflictMsg},
119184 }),
120185 )
121186