git.iko.soy/typeable/oauth2-proxy
on master help sign in
Integrate new header injectors with OAuth2 Proxy
commit18cd045631463168783d48b639b7c8df27a8f2ad authorJoel Speed <joel.speed@hotmail.co.uk> dateWed 29 Jul 2020, 20:10 (6 years ago) parentbea7bb1
7 files changed+484−549
main.go+1−29 oauthproxy.go+68−159 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−159
@@ -2,7 +2,6 @@ package main
22
33import (
44 "context"
5− b64 "encoding/base64"
65 "encoding/json"
76 "errors"
87 "fmt"
@@ -105,6 +104,8 @@ type OAuthProxy struct {
105104 AllowedGroups []string
106105
107106 sessionChain alice.Chain
107+ headersChain alice.Chain
108+ preAuthChain alice.Chain
108109}
109110
110111// NewOAuthProxy creates a new instance of OAuthProxy from the options provided
@@ -163,7 +164,15 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
163164 }
164165 }
165166
167+ preAuthChain, err := buildPreAuthChain(opts)
168+ if err != nil {
169+ return nil, fmt.Errorf("could not build pre-auth chain: %v", err)
170+ }
166171 sessionChain := buildSessionChain(opts, sessionStore, basicAuthValidator)
172+ headersChain, err := buildHeadersChain(opts)
173+ if err != nil {
174+ return nil, fmt.Errorf("could not build headers chain: %v", err)
175+ }
167176
168177 return &OAuthProxy{
169178 CookieName: opts.Cookie.Name,
@@ -195,21 +204,11 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
195204 whitelistDomains: opts.WhitelistDomains,
196205 skipAuthRegex: opts.SkipAuthRegex,
197206 skipAuthPreflight: opts.SkipAuthPreflight,
198− skipAuthStripHeaders: opts.SkipAuthStripHeaders,
199207 skipJwtBearerTokens: opts.SkipJwtBearerTokens,
200208 mainJwtBearerVerifier: opts.GetOIDCVerifier(),
201209 extraJwtBearerVerifiers: opts.GetJWTBearerVerifiers(),
202210 compiledRegex: opts.GetCompiledRegex(),
203211 realClientIPParser: opts.GetRealClientIPParser(),
204− SetXAuthRequest: opts.SetXAuthRequest,
205− PassBasicAuth: opts.PassBasicAuth,
206− SetBasicAuth: opts.SetBasicAuth,
207− PassUserHeaders: opts.PassUserHeaders,
208− BasicAuthPassword: opts.BasicAuthPassword,
209− PassAccessToken: opts.PassAccessToken,
210− SetAuthorization: opts.SetAuthorization,
211− PassAuthorization: opts.PassAuthorization,
212− PreferEmailToUser: opts.PreferEmailToUser,
213212 SkipProviderButton: opts.SkipProviderButton,
214213 templates: templates,
215214 trustedIPs: trustedIPs,
@@ -221,12 +220,46 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
221220 basicAuthValidator: basicAuthValidator,
222221 displayHtpasswdForm: basicAuthValidator != nil,
223222 sessionChain: sessionChain,
223+ headersChain: headersChain,
224+ preAuthChain: preAuthChain,
224225 }, nil
225226}
226227
227−func buildSessionChain(opts *options.Options, sessionStore sessionsapi.SessionStore, validator basic.Validator) alice.Chain {
228+// buildPreAuthChain constructs a chain that should process every request before
229+// the OAuth2 Proxy authentication logic kicks in.
230+// For example forcing HTTPS or health checks.
231+func buildPreAuthChain(opts *options.Options) (alice.Chain, error) {
228232 chain := alice.New(middleware.NewScope())
229233
234+ if opts.ForceHTTPS {
235+ _, httpsPort, err := net.SplitHostPort(opts.HTTPSAddress)
236+ if err != nil {
237+ return alice.Chain{}, fmt.Errorf("invalid HTTPS address %q: %v", opts.HTTPAddress, err)
238+ }
239+ chain = chain.Append(middleware.NewRedirectToHTTPS(httpsPort))
240+ }
241+
242+ healthCheckPaths := []string{opts.PingPath}
243+ healthCheckUserAgents := []string{opts.PingUserAgent}
244+ if opts.GCPHealthChecks {
245+ healthCheckPaths = append(healthCheckPaths, "/liveness_check", "/readiness_check")
246+ healthCheckUserAgents = append(healthCheckUserAgents, "GoogleHC/1.0")
247+ }
248+
249+ // To silence logging of health checks, register the health check handler before
250+ // the logging handler
251+ if opts.Logging.SilencePing {
252+ chain = chain.Append(middleware.NewHealthCheck(healthCheckPaths, healthCheckUserAgents), LoggingHandler)
253+ } else {
254+ chain = chain.Append(LoggingHandler, middleware.NewHealthCheck(healthCheckPaths, healthCheckUserAgents))
255+ }
256+
257+ return chain, nil
258+}
259+
260+func buildSessionChain(opts *options.Options, sessionStore sessionsapi.SessionStore, validator basic.Validator) alice.Chain {
261+ chain := alice.New()
262+
230263 if opts.SkipJwtBearerTokens {
231264 sessionLoaders := []middlewareapi.TokenToSessionLoader{}
232265 if opts.GetOIDCVerifier() != nil {
@@ -259,6 +292,20 @@ func buildSessionChain(opts *options.Options, sessionStore sessionsapi.SessionSt
259292 return chain
260293}
261294
295+func buildHeadersChain(opts *options.Options) (alice.Chain, error) {
296+ requestInjector, err := middleware.NewRequestHeaderInjector(opts.InjectRequestHeaders)
297+ if err != nil {
298+ return alice.Chain{}, fmt.Errorf("error constructing request header injector: %v", err)
299+ }
300+
301+ responseInjector, err := middleware.NewResponseHeaderInjector(opts.InjectResponseHeaders)
302+ if err != nil {
303+ return alice.Chain{}, fmt.Errorf("error constructing request header injector: %v", err)
304+ }
305+
306+ return alice.New(requestInjector, responseInjector), nil
307+}
308+
262309func buildSignInMessage(opts *options.Options) string {
263310 var msg string
264311 if len(opts.Banner) >= 1 {
@@ -636,6 +683,10 @@ func (p *OAuthProxy) IsTrustedIP(req *http.Request) bool {
636683}
637684
638685func (p *OAuthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
686+ p.preAuthChain.Then(http.HandlerFunc(p.serveHTTP)).ServeHTTP(rw, req)
687+}
688+
689+func (p *OAuthProxy) serveHTTP(rw http.ResponseWriter, req *http.Request) {
639690 if req.URL.Path != p.AuthOnlyPath && strings.HasPrefix(req.URL.Path, p.ProxyPrefix) {
640691 prepareNoCache(rw)
641692 }
@@ -828,15 +879,14 @@ func (p *OAuthProxy) AuthenticateOnly(rw http.ResponseWriter, req *http.Request)
828879
829880 // we are authenticated
830881 p.addHeadersForProxying(rw, req, session)
831− rw.WriteHeader(http.StatusAccepted)
882+ p.headersChain.Then(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
883+ rw.WriteHeader(http.StatusAccepted)
884+ })).ServeHTTP(rw, req)
832885}
833886
834887// SkipAuthProxy proxies whitelisted requests and skips authentication
835888func (p *OAuthProxy) SkipAuthProxy(rw http.ResponseWriter, req *http.Request) {
836− if p.skipAuthStripHeaders {
837− p.stripAuthHeaders(req)
838− }
839− p.serveMux.ServeHTTP(rw, req)
889+ p.headersChain.Then(p.serveMux).ServeHTTP(rw, req)
840890}
841891
842892// Proxy proxies the user request if the user is authenticated else it prompts
@@ -847,8 +897,7 @@ func (p *OAuthProxy) Proxy(rw http.ResponseWriter, req *http.Request) {
847897 case nil:
848898 // we are authenticated
849899 p.addHeadersForProxying(rw, req, session)
850− p.serveMux.ServeHTTP(rw, req)
851−
900+ p.headersChain.Then(p.serveMux).ServeHTTP(rw, req)
852901 case ErrNeedsLogin:
853902 // we need to send the user to a login screen
854903 if isAjax(req) {
@@ -905,120 +954,6 @@ func (p *OAuthProxy) getAuthenticatedSession(rw http.ResponseWriter, req *http.R
905954
906955// addHeadersForProxying adds the appropriate headers the request / response for proxying
907956func (p *OAuthProxy) addHeadersForProxying(rw http.ResponseWriter, req *http.Request, session *sessionsapi.SessionState) {
908− if p.PassBasicAuth {
909− if p.PreferEmailToUser && session.Email != "" {
910− req.SetBasicAuth(session.Email, p.BasicAuthPassword)
911− req.Header["X-Forwarded-User"] = []string{session.Email}
912− req.Header.Del("X-Forwarded-Email")
913− } else {
914− req.SetBasicAuth(session.User, p.BasicAuthPassword)
915− req.Header["X-Forwarded-User"] = []string{session.User}
916− if session.Email != "" {
917− req.Header["X-Forwarded-Email"] = []string{session.Email}
918− } else {
919− req.Header.Del("X-Forwarded-Email")
920− }
921− }
922− if session.PreferredUsername != "" {
923− req.Header["X-Forwarded-Preferred-Username"] = []string{session.PreferredUsername}
924− } else {
925− req.Header.Del("X-Forwarded-Preferred-Username")
926− }
927− }
928−
929− if p.PassUserHeaders {
930− if p.PreferEmailToUser && session.Email != "" {
931− req.Header["X-Forwarded-User"] = []string{session.Email}
932− req.Header.Del("X-Forwarded-Email")
933− } else {
934− req.Header["X-Forwarded-User"] = []string{session.User}
935− if session.Email != "" {
936− req.Header["X-Forwarded-Email"] = []string{session.Email}
937− } else {
938− req.Header.Del("X-Forwarded-Email")
939− }
940− }
941−
942− if session.PreferredUsername != "" {
943− req.Header["X-Forwarded-Preferred-Username"] = []string{session.PreferredUsername}
944− } else {
945− req.Header.Del("X-Forwarded-Preferred-Username")
946− }
947−
948− if len(session.Groups) > 0 {
949− for _, group := range session.Groups {
950− req.Header.Add("X-Forwarded-Groups", group)
951− }
952− } else {
953− req.Header.Del("X-Forwarded-Groups")
954− }
955− }
956−
957− if p.SetXAuthRequest {
958− rw.Header().Set("X-Auth-Request-User", session.User)
959− if session.Email != "" {
960− rw.Header().Set("X-Auth-Request-Email", session.Email)
961− } else {
962− rw.Header().Del("X-Auth-Request-Email")
963− }
964− if session.PreferredUsername != "" {
965− rw.Header().Set("X-Auth-Request-Preferred-Username", session.PreferredUsername)
966− } else {
967− rw.Header().Del("X-Auth-Request-Preferred-Username")
968− }
969−
970− if p.PassAccessToken {
971− if session.AccessToken != "" {
972− rw.Header().Set("X-Auth-Request-Access-Token", session.AccessToken)
973− } else {
974− rw.Header().Del("X-Auth-Request-Access-Token")
975− }
976− }
977−
978− if len(session.Groups) > 0 {
979− for _, group := range session.Groups {
980− rw.Header().Add("X-Auth-Request-Groups", group)
981− }
982− } else {
983− rw.Header().Del("X-Auth-Request-Groups")
984− }
985− }
986−
987− if p.PassAccessToken {
988− if session.AccessToken != "" {
989− req.Header["X-Forwarded-Access-Token"] = []string{session.AccessToken}
990− } else {
991− req.Header.Del("X-Forwarded-Access-Token")
992− }
993− }
994−
995− if p.PassAuthorization {
996− if session.IDToken != "" {
997− req.Header["Authorization"] = []string{fmt.Sprintf("Bearer %s", session.IDToken)}
998− } else {
999− req.Header.Del("Authorization")
1000− }
1001− }
1002− if p.SetBasicAuth {
1003− switch {
1004− case p.PreferEmailToUser && session.Email != "":
1005− authVal := b64.StdEncoding.EncodeToString([]byte(session.Email + ":" + p.BasicAuthPassword))
1006− rw.Header().Set("Authorization", "Basic "+authVal)
1007− case session.User != "":
1008− authVal := b64.StdEncoding.EncodeToString([]byte(session.User + ":" + p.BasicAuthPassword))
1009− rw.Header().Set("Authorization", "Basic "+authVal)
1010− default:
1011− rw.Header().Del("Authorization")
1012− }
1013− }
1014− if p.SetAuthorization {
1015− if session.IDToken != "" {
1016− rw.Header().Set("Authorization", fmt.Sprintf("Bearer %s", session.IDToken))
1017− } else {
1018− rw.Header().Del("Authorization")
1019− }
1020− }
1021−
1022957 if session.Email == "" {
1023958 rw.Header().Set("GAP-Auth", session.User)
1024959 } else {
@@ -1026,32 +961,6 @@ func (p *OAuthProxy) addHeadersForProxying(rw http.ResponseWriter, req *http.Req
1026961 }
1027962}
1028963
1029−// stripAuthHeaders removes Auth headers for whitelisted routes from skipAuthRegex
1030−func (p *OAuthProxy) stripAuthHeaders(req *http.Request) {
1031− if p.PassBasicAuth {
1032− req.Header.Del("X-Forwarded-User")
1033− req.Header.Del("X-Forwarded-Groups")
1034− req.Header.Del("X-Forwarded-Email")
1035− req.Header.Del("X-Forwarded-Preferred-Username")
1036− req.Header.Del("Authorization")
1037− }
1038−
1039− if p.PassUserHeaders {
1040− req.Header.Del("X-Forwarded-User")
1041− req.Header.Del("X-Forwarded-Groups")
1042− req.Header.Del("X-Forwarded-Email")
1043− req.Header.Del("X-Forwarded-Preferred-Username")
1044− }
1045−
1046− if p.PassAccessToken {
1047− req.Header.Del("X-Forwarded-Access-Token")
1048− }
1049−
1050− if p.PassAuthorization {
1051− req.Header.Del("Authorization")
1052− }
1053−}
1054−
1055964// isAjax checks if a request is an ajax request
1056965func isAjax(req *http.Request) bool {
1057966 acceptValues := req.Header.Values("Accept")
oauthproxy_test.go+318−301
@@ -423,6 +423,8 @@ func TestBasicAuthPassword(t *testing.T) {
423423 t.Fatal(err)
424424 }
425425 }))
426+
427+ basicAuthPassword := "This is a secure password"
426428 opts := baseTestOptions()
427429 opts.UpstreamServers = options.Upstreams{
428430 {
@@ -433,11 +435,22 @@ func TestBasicAuthPassword(t *testing.T) {
433435 }
434436
435437 opts.Cookie.Secure = false
436− opts.PassBasicAuth = true
437− opts.SetBasicAuth = true
438− opts.PassUserHeaders = true
439− opts.PreferEmailToUser = true
440− opts.BasicAuthPassword = "This is a secure password"
438+ opts.InjectRequestHeaders = []options.Header{
439+ {
440+ Name: "Authorization",
441+ Values: []options.HeaderValue{
442+ {
443+ ClaimSource: &options.ClaimSource{
444+ Claim: "email",
445+ BasicAuthPassword: &options.SecretSource{
446+ Value: []byte(base64.StdEncoding.EncodeToString([]byte(basicAuthPassword))),
447+ },
448+ },
449+ },
450+ },
451+ },
452+ }
453+
441454 err := validation.Validate(opts)
442455 assert.NoError(t, err)
443456
@@ -452,148 +465,44 @@ func TestBasicAuthPassword(t *testing.T) {
452465 t.Fatal(err)
453466 }
454467
468+ // Save the required session
455469 rw := httptest.NewRecorder()
456− req, _ := http.NewRequest("GET", "/oauth2/callback?code=callback_code&state=nonce:", strings.NewReader(""))
457− req.AddCookie(proxy.MakeCSRFCookie(req, "nonce", proxy.CookieExpire, time.Now()))
458− proxy.ServeHTTP(rw, req)
459− if rw.Code >= 400 {
460− t.Fatalf("expected 3xx got %d", rw.Code)
461− }
462− cookie := rw.Header().Values("Set-Cookie")[1]
463−
464− cookieName := proxy.CookieName
465− var value string
466− keyPrefix := cookieName + "="
467−
468− for _, field := range strings.Split(cookie, "; ") {
469− value = strings.TrimPrefix(field, keyPrefix)
470− if value != field {
471− break
472− } else {
473− value = ""
474− }
475− }
476−
477− req, _ = http.NewRequest("GET", "/", strings.NewReader(""))
478− req.AddCookie(&http.Cookie{
479− Name: cookieName,
480− Value: value,
481− Path: "/",
482− Expires: time.Now().Add(time.Duration(24)),
483− HttpOnly: true,
470+ req, _ := http.NewRequest("GET", "/", nil)
471+ err = proxy.sessionStore.Save(rw, req, &sessions.SessionState{
472+ Email: emailAddress,
484473 })
485− req.AddCookie(proxy.MakeCSRFCookie(req, "nonce", proxy.CookieExpire, time.Now()))
474+ assert.NoError(t, err)
486475
476+ // Extract the cookie value to inject into the test request
477+ cookie := rw.Header().Values("Set-Cookie")[0]
478+
479+ req, _ = http.NewRequest("GET", "/", nil)
480+ req.Header.Set("Cookie", cookie)
487481 rw = httptest.NewRecorder()
488482 proxy.ServeHTTP(rw, req)
489483
490484 // The username in the basic auth credentials is expected to be equal to the email address from the
491485 // auth response, so we use the same variable here.
492− expectedHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte(emailAddress+":"+opts.BasicAuthPassword))
486+ expectedHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte(emailAddress+":"+basicAuthPassword))
493487 assert.Equal(t, expectedHeader, rw.Body.String())
494488 providerServer.Close()
495489}
496490
497−func TestBasicAuthWithEmail(t *testing.T) {
498− opts := baseTestOptions()
499− opts.PassBasicAuth = true
500− opts.PassUserHeaders = false
501− opts.PreferEmailToUser = false
502− opts.BasicAuthPassword = "This is a secure password"
503− err := validation.Validate(opts)
504− assert.NoError(t, err)
505−
506− const emailAddress = "john.doe@example.com"
507− const userName = "9fcab5c9b889a557"
508−
509− // The username in the basic auth credentials is expected to be equal to the email address from the
510− expectedEmailHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte(emailAddress+":"+opts.BasicAuthPassword))
511− expectedUserHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte(userName+":"+opts.BasicAuthPassword))
512−
513− created := time.Now()
514− session := &sessions.SessionState{
515− User: userName,
516− Email: emailAddress,
517− AccessToken: "oauth_token",
518− CreatedAt: &created,
519− }
520− {
521− rw := httptest.NewRecorder()
522− req, _ := http.NewRequest("GET", opts.ProxyPrefix+"/testCase0", nil)
523− proxy, err := NewOAuthProxy(opts, func(email string) bool {
524− return email == emailAddress
525− })
526− if err != nil {
527− t.Fatal(err)
528− }
529− proxy.addHeadersForProxying(rw, req, session)
530− assert.Equal(t, expectedUserHeader, req.Header["Authorization"][0])
531− assert.Equal(t, userName, req.Header["X-Forwarded-User"][0])
532− }
533−
534− opts.PreferEmailToUser = true
535− {
536− rw := httptest.NewRecorder()
537− req, _ := http.NewRequest("GET", opts.ProxyPrefix+"/testCase1", nil)
538−
539− proxy, err := NewOAuthProxy(opts, func(email string) bool {
540− return email == emailAddress
541− })
542− if err != nil {
543− t.Fatal(err)
544− }
545− proxy.addHeadersForProxying(rw, req, session)
546− assert.Equal(t, expectedEmailHeader, req.Header["Authorization"][0])
547− assert.Equal(t, emailAddress, req.Header["X-Forwarded-User"][0])
548− }
549−}
550−
551−func TestPassUserHeadersWithEmail(t *testing.T) {
491+func TestPassGroupsHeadersWithGroups(t *testing.T) {
552492 opts := baseTestOptions()
553− err := validation.Validate(opts)
554− assert.NoError(t, err)
555−
556− const emailAddress = "john.doe@example.com"
557− const userName = "9fcab5c9b889a557"
558−
559− created := time.Now()
560− session := &sessions.SessionState{
561− User: userName,
562− Email: emailAddress,
563− AccessToken: "oauth_token",
564− CreatedAt: &created,
565− }
566− {
567− rw := httptest.NewRecorder()
568− req, _ := http.NewRequest("GET", opts.ProxyPrefix+"/testCase0", nil)
569− proxy, err := NewOAuthProxy(opts, func(email string) bool {
570− return email == emailAddress
571− })
572− if err != nil {
573− t.Fatal(err)
574− }
575− proxy.addHeadersForProxying(rw, req, session)
576− assert.Equal(t, userName, req.Header["X-Forwarded-User"][0])
577− }
578−
579− opts.PreferEmailToUser = true
580− {
581− rw := httptest.NewRecorder()
582− req, _ := http.NewRequest("GET", opts.ProxyPrefix+"/testCase1", nil)
583−
584− proxy, err := NewOAuthProxy(opts, func(email string) bool {
585− return email == emailAddress
586− })
587− if err != nil {
588− t.Fatal(err)
589− }
590− proxy.addHeadersForProxying(rw, req, session)
591− assert.Equal(t, emailAddress, req.Header["X-Forwarded-User"][0])
493+ opts.InjectRequestHeaders = []options.Header{
494+ {
495+ Name: "X-Forwarded-Groups",
496+ Values: []options.HeaderValue{
497+ {
498+ ClaimSource: &options.ClaimSource{
499+ Claim: "groups",
500+ },
501+ },
502+ },
503+ },
592504 }
593−}
594505
595−func TestPassGroupsHeadersWithGroups(t *testing.T) {
596− opts := baseTestOptions()
597506 err := validation.Validate(opts)
598507 assert.NoError(t, err)
599508
@@ -609,161 +518,27 @@ func TestPassGroupsHeadersWithGroups(t *testing.T) {
609518 AccessToken: "oauth_token",
610519 CreatedAt: &created,
611520 }
612− {
613− rw := httptest.NewRecorder()
614− req, _ := http.NewRequest("GET", opts.ProxyPrefix+"/testCase0", nil)
615− proxy, err := NewOAuthProxy(opts, func(email string) bool {
616− return email == emailAddress
617− })
618− if err != nil {
619− t.Fatal(err)
620− }
621− proxy.addHeadersForProxying(rw, req, session)
622− assert.Equal(t, groups, req.Header["X-Forwarded-Groups"])
623− }
624−}
625−
626−func TestStripAuthHeaders(t *testing.T) {
627− testCases := map[string]struct {
628− SkipAuthStripHeaders bool
629− PassBasicAuth bool
630− PassUserHeaders bool
631− PassAccessToken bool
632− PassAuthorization bool
633− StrippedHeaders map[string]bool
634− }{
635− "Default options": {
636− SkipAuthStripHeaders: true,
637− PassBasicAuth: true,
638− PassUserHeaders: true,
639− PassAccessToken: false,
640− PassAuthorization: false,
641− StrippedHeaders: map[string]bool{
642− "X-Forwarded-User": true,
643− "X-Forwared-Groups": true,
644− "X-Forwarded-Email": true,
645− "X-Forwarded-Preferred-Username": true,
646− "X-Forwarded-Access-Token": false,
647− "Authorization": true,
648− },
649− },
650− "Pass access token": {
651− SkipAuthStripHeaders: true,
652− PassBasicAuth: true,
653− PassUserHeaders: true,
654− PassAccessToken: true,
655− PassAuthorization: false,
656− StrippedHeaders: map[string]bool{
657− "X-Forwarded-User": true,
658− "X-Forwared-Groups": true,
659− "X-Forwarded-Email": true,
660− "X-Forwarded-Preferred-Username": true,
661− "X-Forwarded-Access-Token": true,
662− "Authorization": true,
663− },
664− },
665− "Nothing setting Authorization": {
666− SkipAuthStripHeaders: true,
667− PassBasicAuth: false,
668− PassUserHeaders: true,
669− PassAccessToken: true,
670− PassAuthorization: false,
671− StrippedHeaders: map[string]bool{
672− "X-Forwarded-User": true,
673− "X-Forwared-Groups": true,
674− "X-Forwarded-Email": true,
675− "X-Forwarded-Preferred-Username": true,
676− "X-Forwarded-Access-Token": true,
677− "Authorization": false,
678− },
679− },
680− "Only Authorization header modified": {
681− SkipAuthStripHeaders: true,
682− PassBasicAuth: false,
683− PassUserHeaders: false,
684− PassAccessToken: false,
685− PassAuthorization: true,
686− StrippedHeaders: map[string]bool{
687− "X-Forwarded-User": false,
688− "X-Forwared-Groups": false,
689− "X-Forwarded-Email": false,
690− "X-Forwarded-Preferred-Username": false,
691− "X-Forwarded-Access-Token": false,
692− "Authorization": true,
693− },
694− },
695− "Don't strip any headers (default options)": {
696− SkipAuthStripHeaders: false,
697− PassBasicAuth: true,
698− PassUserHeaders: true,
699− PassAccessToken: false,
700− PassAuthorization: false,
701− StrippedHeaders: map[string]bool{
702− "X-Forwarded-User": false,
703− "X-Forwared-Groups": false,
704− "X-Forwarded-Email": false,
705− "X-Forwarded-Preferred-Username": false,
706− "X-Forwarded-Access-Token": false,
707− "Authorization": false,
708− },
709− },
710− "Don't strip any headers (custom options)": {
711− SkipAuthStripHeaders: false,
712− PassBasicAuth: true,
713− PassUserHeaders: true,
714− PassAccessToken: true,
715− PassAuthorization: false,
716− StrippedHeaders: map[string]bool{
717− "X-Forwarded-User": false,
718− "X-Forwared-Groups": false,
719− "X-Forwarded-Email": false,
720− "X-Forwarded-Preferred-Username": false,
721− "X-Forwarded-Access-Token": false,
722− "Authorization": false,
723− },
724− },
725− }
726521
727− initialHeaders := map[string]string{
728− "X-Forwarded-User": "9fcab5c9b889a557",
729− "X-Forwarded-Email": "john.doe@example.com",
730− "X-Forwarded-Groups": "a,b,c",
731− "X-Forwarded-Preferred-Username": "john.doe",
732− "X-Forwarded-Access-Token": "AccessToken",
733− "Authorization": "bearer IDToken",
734− }
522+ proxy, err := NewOAuthProxy(opts, func(email string) bool {
523+ return email == emailAddress
524+ })
525+ assert.NoError(t, err)
735526
736− for name, tc := range testCases {
737− t.Run(name, func(t *testing.T) {
738− opts := baseTestOptions()
739− opts.SkipAuthStripHeaders = tc.SkipAuthStripHeaders
740− opts.PassBasicAuth = tc.PassBasicAuth
741− opts.PassUserHeaders = tc.PassUserHeaders
742− opts.PassAccessToken = tc.PassAccessToken
743− opts.PassAuthorization = tc.PassAuthorization
744− err := validation.Validate(opts)
745− assert.NoError(t, err)
527+ // Save the required session
528+ rw := httptest.NewRecorder()
529+ req, _ := http.NewRequest("GET", "/", nil)
530+ err = proxy.sessionStore.Save(rw, req, session)
531+ assert.NoError(t, err)
746532
747− req, _ := http.NewRequest("GET", fmt.Sprintf("%s/testCase", opts.ProxyPrefix), nil)
748− for header, val := range initialHeaders {
749− req.Header.Set(header, val)
750− }
533+ // Extract the cookie value to inject into the test request
534+ cookie := rw.Header().Values("Set-Cookie")[0]
751535
752− proxy, err := NewOAuthProxy(opts, func(_ string) bool { return true })
753− assert.NoError(t, err)
754− if proxy.skipAuthStripHeaders {
755− proxy.stripAuthHeaders(req)
756− }
536+ req, _ = http.NewRequest("GET", "/", nil)
537+ req.Header.Set("Cookie", cookie)
538+ rw = httptest.NewRecorder()
539+ proxy.ServeHTTP(rw, req)
757540
758− for header, stripped := range tc.StrippedHeaders {
759− if stripped {
760− assert.Equal(t, req.Header.Get(header), "")
761− } else {
762− assert.Equal(t, req.Header.Get(header), initialHeaders[header])
763− }
764− }
765− })
766− }
541+ assert.Equal(t, groups, req.Header["X-Forwarded-Groups"])
767542}
768543
769544type PassAccessTokenTest struct {
@@ -812,7 +587,21 @@ func NewPassAccessTokenTest(opts PassAccessTokenTestOptions) (*PassAccessTokenTe
812587 }
813588
814589 patt.opts.Cookie.Secure = false
815− patt.opts.PassAccessToken = opts.PassAccessToken
590+ if opts.PassAccessToken {
591+ patt.opts.InjectRequestHeaders = []options.Header{
592+ {
593+ Name: "X-Forwarded-Access-Token",
594+ Values: []options.HeaderValue{
595+ {
596+ ClaimSource: &options.ClaimSource{
597+ Claim: "access_token",
598+ },
599+ },
600+ },
601+ },
602+ }
603+ }
604+
816605 err := validation.Validate(patt.opts)
817606 if err != nil {
818607 return nil, err
@@ -1370,7 +1159,48 @@ func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) {
13701159 var pcTest ProcessCookieTest
13711160
13721161 pcTest.opts = baseTestOptions()
1373− pcTest.opts.SetXAuthRequest = true
1162+ pcTest.opts.InjectResponseHeaders = []options.Header{
1163+ {
1164+ Name: "X-Auth-Request-User",
1165+ Values: []options.HeaderValue{
1166+ {
1167+ ClaimSource: &options.ClaimSource{
1168+ Claim: "user",
1169+ },
1170+ },
1171+ },
1172+ },
1173+ {
1174+ Name: "X-Auth-Request-Email",
1175+ Values: []options.HeaderValue{
1176+ {
1177+ ClaimSource: &options.ClaimSource{
1178+ Claim: "email",
1179+ },
1180+ },
1181+ },
1182+ },
1183+ {
1184+ Name: "X-Auth-Request-Groups",
1185+ Values: []options.HeaderValue{
1186+ {
1187+ ClaimSource: &options.ClaimSource{
1188+ Claim: "groups",
1189+ },
1190+ },
1191+ },
1192+ },
1193+ {
1194+ Name: "X-Forwarded-Preferred-Username",
1195+ Values: []options.HeaderValue{
1196+ {
1197+ ClaimSource: &options.ClaimSource{
1198+ Claim: "preferred_username",
1199+ },
1200+ },
1201+ },
1202+ },
1203+ }
13741204 pcTest.opts.AllowedGroups = []string{"oauth_groups"}
13751205 err := validation.Validate(pcTest.opts)
13761206 assert.NoError(t, err)
@@ -1408,8 +1238,62 @@ func TestAuthOnlyEndpointSetBasicAuthTrueRequestHeaders(t *testing.T) {
14081238 var pcTest ProcessCookieTest
14091239
14101240 pcTest.opts = baseTestOptions()
1411− pcTest.opts.SetXAuthRequest = true
1412− pcTest.opts.SetBasicAuth = true
1241+ pcTest.opts.InjectResponseHeaders = []options.Header{
1242+ {
1243+ Name: "X-Auth-Request-User",
1244+ Values: []options.HeaderValue{
1245+ {
1246+ ClaimSource: &options.ClaimSource{
1247+ Claim: "user",
1248+ },
1249+ },
1250+ },
1251+ },
1252+ {
1253+ Name: "X-Auth-Request-Email",
1254+ Values: []options.HeaderValue{
1255+ {
1256+ ClaimSource: &options.ClaimSource{
1257+ Claim: "email",
1258+ },
1259+ },
1260+ },
1261+ },
1262+ {
1263+ Name: "X-Auth-Request-Groups",
1264+ Values: []options.HeaderValue{
1265+ {
1266+ ClaimSource: &options.ClaimSource{
1267+ Claim: "groups",
1268+ },
1269+ },
1270+ },
1271+ },
1272+ {
1273+ Name: "X-Forwarded-Preferred-Username",
1274+ Values: []options.HeaderValue{
1275+ {
1276+ ClaimSource: &options.ClaimSource{
1277+ Claim: "preferred_username",
1278+ },
1279+ },
1280+ },
1281+ },
1282+ {
1283+ Name: "Authorization",
1284+ Values: []options.HeaderValue{
1285+ {
1286+ ClaimSource: &options.ClaimSource{
1287+ Claim: "user",
1288+ BasicAuthPassword: &options.SecretSource{
1289+ Value: []byte(base64.StdEncoding.EncodeToString([]byte("This is a secure password"))),
1290+ },
1291+ },
1292+ },
1293+ },
1294+ },
1295+ }
1296+
14131297 err := validation.Validate(pcTest.opts)
14141298 assert.NoError(t, err)
14151299
@@ -1439,7 +1323,7 @@ func TestAuthOnlyEndpointSetBasicAuthTrueRequestHeaders(t *testing.T) {
14391323 assert.Equal(t, http.StatusAccepted, pcTest.rw.Code)
14401324 assert.Equal(t, "oauth_user", pcTest.rw.Header().Values("X-Auth-Request-User")[0])
14411325 assert.Equal(t, "oauth_user@example.com", pcTest.rw.Header().Values("X-Auth-Request-Email")[0])
1442− expectedHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte("oauth_user:"+pcTest.opts.BasicAuthPassword))
1326+ expectedHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte("oauth_user:This is a secure password"))
14431327 assert.Equal(t, expectedHeader, pcTest.rw.Header().Values("Authorization")[0])
14441328}
14451329
@@ -1447,8 +1331,48 @@ func TestAuthOnlyEndpointSetBasicAuthFalseRequestHeaders(t *testing.T) {
14471331 var pcTest ProcessCookieTest
14481332
14491333 pcTest.opts = baseTestOptions()
1450− pcTest.opts.SetXAuthRequest = true
1451− pcTest.opts.SetBasicAuth = false
1334+ pcTest.opts.InjectResponseHeaders = []options.Header{
1335+ {
1336+ Name: "X-Auth-Request-User",
1337+ Values: []options.HeaderValue{
1338+ {
1339+ ClaimSource: &options.ClaimSource{
1340+ Claim: "user",
1341+ },
1342+ },
1343+ },
1344+ },
1345+ {
1346+ Name: "X-Auth-Request-Email",
1347+ Values: []options.HeaderValue{
1348+ {
1349+ ClaimSource: &options.ClaimSource{
1350+ Claim: "email",
1351+ },
1352+ },
1353+ },
1354+ },
1355+ {
1356+ Name: "X-Auth-Request-Groups",
1357+ Values: []options.HeaderValue{
1358+ {
1359+ ClaimSource: &options.ClaimSource{
1360+ Claim: "groups",
1361+ },
1362+ },
1363+ },
1364+ },
1365+ {
1366+ Name: "X-Forwarded-Preferred-Username",
1367+ Values: []options.HeaderValue{
1368+ {
1369+ ClaimSource: &options.ClaimSource{
1370+ Claim: "preferred_username",
1371+ },
1372+ },
1373+ },
1374+ },
1375+ }
14521376 err := validation.Validate(pcTest.opts)
14531377 assert.NoError(t, err)
14541378
@@ -1913,9 +1837,74 @@ func TestGetJwtSession(t *testing.T) {
19131837 &oidc.Config{ClientID: "https://test.myapp.com", SkipExpiryCheck: true})
19141838
19151839 test, err := NewAuthOnlyEndpointTest(func(opts *options.Options) {
1916− opts.PassAuthorization = true
1917− opts.SetAuthorization = true
1918− opts.SetXAuthRequest = true
1840+ opts.InjectRequestHeaders = []options.Header{
1841+ {
1842+ Name: "Authorization",
1843+ Values: []options.HeaderValue{
1844+ {
1845+ ClaimSource: &options.ClaimSource{
1846+ Claim: "id_token",
1847+ Prefix: "Bearer ",
1848+ },
1849+ },
1850+ },
1851+ },
1852+ {
1853+ Name: "X-Forwarded-User",
1854+ Values: []options.HeaderValue{
1855+ {
1856+ ClaimSource: &options.ClaimSource{
1857+ Claim: "user",
1858+ },
1859+ },
1860+ },
1861+ },
1862+ {
1863+ Name: "X-Forwarded-Email",
1864+ Values: []options.HeaderValue{
1865+ {
1866+ ClaimSource: &options.ClaimSource{
1867+ Claim: "email",
1868+ },
1869+ },
1870+ },
1871+ },
1872+ }
1873+
1874+ opts.InjectResponseHeaders = []options.Header{
1875+ {
1876+ Name: "Authorization",
1877+ Values: []options.HeaderValue{
1878+ {
1879+ ClaimSource: &options.ClaimSource{
1880+ Claim: "id_token",
1881+ Prefix: "Bearer ",
1882+ },
1883+ },
1884+ },
1885+ },
1886+ {
1887+ Name: "X-Auth-Request-User",
1888+ Values: []options.HeaderValue{
1889+ {
1890+ ClaimSource: &options.ClaimSource{
1891+ Claim: "user",
1892+ },
1893+ },
1894+ },
1895+ },
1896+ {
1897+ Name: "X-Auth-Request-Email",
1898+ Values: []options.HeaderValue{
1899+ {
1900+ ClaimSource: &options.ClaimSource{
1901+ Claim: "email",
1902+ },
1903+ },
1904+ },
1905+ },
1906+ }
1907+
19191908 opts.SkipJwtBearerTokens = true
19201909 opts.SetJWTBearerVerifiers(append(opts.GetJWTBearerVerifiers(), verifier))
19211910 })
@@ -1932,15 +1921,6 @@ func TestGetJwtSession(t *testing.T) {
19321921 "Authorization": {authHeader},
19331922 }
19341923
1935− // Bearer
1936− expires := time.Unix(1912151821, 0)
1937− session, err := test.proxy.getAuthenticatedSession(test.rw, test.req)
1938− assert.NoError(t, err)
1939− assert.Equal(t, session.User, "1234567890")
1940− assert.Equal(t, session.Email, "john@example.com")
1941− assert.Equal(t, session.ExpiresOn, &expires)
1942− assert.Equal(t, session.IDToken, goodJwt)
1943−
19441924 test.proxy.ServeHTTP(test.rw, test.req)
19451925 if test.rw.Code >= 400 {
19461926 t.Fatalf("expected 3xx got %d", test.rw.Code)
@@ -2068,6 +2048,43 @@ func baseTestOptions() *options.Options {
20682048 opts.ClientID = clientID
20692049 opts.ClientSecret = clientSecret
20702050 opts.EmailDomains = []string{"*"}
2051+
2052+ // Default injected headers for legacy configuration
2053+ opts.InjectRequestHeaders = []options.Header{
2054+ {
2055+ Name: "Authorization",
2056+ Values: []options.HeaderValue{
2057+ {
2058+ ClaimSource: &options.ClaimSource{
2059+ Claim: "user",
2060+ BasicAuthPassword: &options.SecretSource{
2061+ Value: []byte(base64.StdEncoding.EncodeToString([]byte("This is a secure password"))),
2062+ },
2063+ },
2064+ },
2065+ },
2066+ },
2067+ {
2068+ Name: "X-Forwarded-User",
2069+ Values: []options.HeaderValue{
2070+ {
2071+ ClaimSource: &options.ClaimSource{
2072+ Claim: "user",
2073+ },
2074+ },
2075+ },
2076+ },
2077+ {
2078+ Name: "X-Forwarded-Email",
2079+ Values: []options.HeaderValue{
2080+ {
2081+ ClaimSource: &options.ClaimSource{
2082+ Claim: "email",
2083+ },
2084+ },
2085+ },
2086+ },
2087+ }
20712088 return opts
20722089}
20732090
pkg/validation/options.go−8
@@ -72,10 +72,6 @@ func Validate(o *options.Options) error {
7272 "\n use email-domain=* to authorize all email addresses")
7373 }
7474
75− if o.SetBasicAuth && o.SetAuthorization {
76− msgs = append(msgs, "mutually exclusive: set-basic-auth and set-authorization-header can not both be true")
77− }
78−
7975 if o.OIDCIssuerURL != "" {
8076
8177 ctx := context.Background()
@@ -160,10 +156,6 @@ func Validate(o *options.Options) error {
160156 }
161157 }
162158
163− if o.PreferEmailToUser && !o.PassBasicAuth && !o.PassUserHeaders {
164− msgs = append(msgs, "PreferEmailToUser should only be used with PassBasicAuth or PassUserHeaders")
165− }
166−
167159 if o.SkipJwtBearerTokens {
168160 // Configure extra issuers
169161 if len(o.ExtraJwtIssuers) > 0 {
pkg/validation/options_test.go−23
@@ -191,29 +191,6 @@ func TestDefaultProviderApiSettings(t *testing.T) {
191191 assert.Equal(t, "profile email", p.Scope)
192192}
193193
194−func TestPassAccessTokenRequiresSpecificCookieSecretLengths(t *testing.T) {
195− o := testOptions()
196− assert.Equal(t, nil, Validate(o))
197−
198− assert.Equal(t, false, o.PassAccessToken)
199− o.PassAccessToken = true
200− o.Cookie.Secret = "cookie of invalid length-"
201− assert.NotEqual(t, nil, Validate(o))
202−
203− o.PassAccessToken = false
204− o.Cookie.Refresh = time.Duration(24) * time.Hour
205− assert.NotEqual(t, nil, Validate(o))
206−
207− o.Cookie.Secret = "16 bytes AES-128"
208− assert.Equal(t, nil, Validate(o))
209−
210− o.Cookie.Secret = "24 byte secret AES-192--"
211− assert.Equal(t, nil, Validate(o))
212−
213− o.Cookie.Secret = "32 byte secret for AES-256------"
214− assert.Equal(t, nil, Validate(o))
215−}
216−
217194func TestCookieRefreshMustBeLessThanCookieExpire(t *testing.T) {
218195 o := testOptions()
219196 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