@@ -592,6 +592,37 @@ func TestPassUserHeadersWithEmail(t *testing.T) {
595+func TestPassGroupsHeadersWithGroups(t *testing.T) {
596+ opts := baseTestOptions()
597+ err := validation.Validate(opts)
598+ assert.NoError(t, err)
600+ const emailAddress = "john.doe@example.com"
601+ const userName = "9fcab5c9b889a557"
603+ groups := []string{"a", "b"}
604+ created := time.Now()
605+ session := &sessions.SessionState{
608+ Email: emailAddress,
609+ AccessToken: "oauth_token",
610+ CreatedAt: &created,
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
621+ proxy.addHeadersForProxying(rw, req, session)
622+ assert.Equal(t, groups, req.Header["X-Forwarded-Groups"])
595func TestStripAuthHeaders(t *testing.T) {
626func TestStripAuthHeaders(t *testing.T) {
596 testCases := map[string]struct {
627 testCases := map[string]struct {
597 SkipAuthStripHeaders bool
628 SkipAuthStripHeaders bool
@@ -609,6 +640,7 @@ func TestStripAuthHeaders(t *testing.T) {
609 PassAuthorization: false,
640 PassAuthorization: false,
610 StrippedHeaders: map[string]bool{
641 StrippedHeaders: map[string]bool{
611 "X-Forwarded-User": true,
642 "X-Forwarded-User": true,
643+ "X-Forwared-Groups": true,
612 "X-Forwarded-Email": true,
644 "X-Forwarded-Email": true,
613 "X-Forwarded-Preferred-Username": true,
645 "X-Forwarded-Preferred-Username": true,
614 "X-Forwarded-Access-Token": false,
646 "X-Forwarded-Access-Token": false,
@@ -623,6 +655,7 @@ func TestStripAuthHeaders(t *testing.T) {
623 PassAuthorization: false,
655 PassAuthorization: false,
624 StrippedHeaders: map[string]bool{
656 StrippedHeaders: map[string]bool{
625 "X-Forwarded-User": true,
657 "X-Forwarded-User": true,
658+ "X-Forwared-Groups": true,
626 "X-Forwarded-Email": true,
659 "X-Forwarded-Email": true,
627 "X-Forwarded-Preferred-Username": true,
660 "X-Forwarded-Preferred-Username": true,
628 "X-Forwarded-Access-Token": true,
661 "X-Forwarded-Access-Token": true,
@@ -637,6 +670,7 @@ func TestStripAuthHeaders(t *testing.T) {
637 PassAuthorization: false,
670 PassAuthorization: false,
638 StrippedHeaders: map[string]bool{
671 StrippedHeaders: map[string]bool{
639 "X-Forwarded-User": true,
672 "X-Forwarded-User": true,
673+ "X-Forwared-Groups": true,
640 "X-Forwarded-Email": true,
674 "X-Forwarded-Email": true,
641 "X-Forwarded-Preferred-Username": true,
675 "X-Forwarded-Preferred-Username": true,
642 "X-Forwarded-Access-Token": true,
676 "X-Forwarded-Access-Token": true,
@@ -651,6 +685,7 @@ func TestStripAuthHeaders(t *testing.T) {
651 PassAuthorization: true,
685 PassAuthorization: true,
652 StrippedHeaders: map[string]bool{
686 StrippedHeaders: map[string]bool{
653 "X-Forwarded-User": false,
687 "X-Forwarded-User": false,
688+ "X-Forwared-Groups": false,
654 "X-Forwarded-Email": false,
689 "X-Forwarded-Email": false,
655 "X-Forwarded-Preferred-Username": false,
690 "X-Forwarded-Preferred-Username": false,
656 "X-Forwarded-Access-Token": false,
691 "X-Forwarded-Access-Token": false,
@@ -665,6 +700,7 @@ func TestStripAuthHeaders(t *testing.T) {
665 PassAuthorization: false,
700 PassAuthorization: false,
666 StrippedHeaders: map[string]bool{
701 StrippedHeaders: map[string]bool{
667 "X-Forwarded-User": false,
702 "X-Forwarded-User": false,
703+ "X-Forwared-Groups": false,
668 "X-Forwarded-Email": false,
704 "X-Forwarded-Email": false,
669 "X-Forwarded-Preferred-Username": false,
705 "X-Forwarded-Preferred-Username": false,
670 "X-Forwarded-Access-Token": false,
706 "X-Forwarded-Access-Token": false,
@@ -679,6 +715,7 @@ func TestStripAuthHeaders(t *testing.T) {
679 PassAuthorization: false,
715 PassAuthorization: false,
680 StrippedHeaders: map[string]bool{
716 StrippedHeaders: map[string]bool{
681 "X-Forwarded-User": false,
717 "X-Forwarded-User": false,
718+ "X-Forwared-Groups": false,
682 "X-Forwarded-Email": false,
719 "X-Forwarded-Email": false,
683 "X-Forwarded-Preferred-Username": false,
720 "X-Forwarded-Preferred-Username": false,
684 "X-Forwarded-Access-Token": false,
721 "X-Forwarded-Access-Token": false,
@@ -690,6 +727,7 @@ func TestStripAuthHeaders(t *testing.T) {
690 initialHeaders := map[string]string{
727 initialHeaders := map[string]string{
691 "X-Forwarded-User": "9fcab5c9b889a557",
728 "X-Forwarded-User": "9fcab5c9b889a557",
692 "X-Forwarded-Email": "john.doe@example.com",
729 "X-Forwarded-Email": "john.doe@example.com",
730+ "X-Forwarded-Groups": "a,b,c",
693 "X-Forwarded-Preferred-Username": "john.doe",
731 "X-Forwarded-Preferred-Username": "john.doe",
694 "X-Forwarded-Access-Token": "AccessToken",
732 "X-Forwarded-Access-Token": "AccessToken",
695 "Authorization": "bearer IDToken",
733 "Authorization": "bearer IDToken",
@@ -1333,6 +1371,7 @@ func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) {
1334 pcTest.opts = baseTestOptions()
1372 pcTest.opts = baseTestOptions()
1335 pcTest.opts.SetXAuthRequest = true
1373 pcTest.opts.SetXAuthRequest = true
1374+ pcTest.opts.AllowedGroups = []string{"oauth_groups"}
1336 err := validation.Validate(pcTest.opts)
1375 err := validation.Validate(pcTest.opts)
1337 assert.NoError(t, err)
1376 assert.NoError(t, err)
@@ -1354,13 +1393,14 @@ func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) {
1355 created := time.Now()
1394 created := time.Now()
1356 startSession := &sessions.SessionState{
1395 startSession := &sessions.SessionState{
1357− User: "oauth_user", Email: "oauth_user@example.com", AccessToken: "oauth_token", CreatedAt: &created}
1396+ User: "oauth_user", Groups: []string{"oauth_groups"}, Email: "oauth_user@example.com", AccessToken: "oauth_token", CreatedAt: &created}
1358 err = pcTest.SaveSession(startSession)
1397 err = pcTest.SaveSession(startSession)
1359 assert.NoError(t, err)
1398 assert.NoError(t, err)
1361 pcTest.proxy.ServeHTTP(pcTest.rw, pcTest.req)
1400 pcTest.proxy.ServeHTTP(pcTest.rw, pcTest.req)
1362 assert.Equal(t, http.StatusAccepted, pcTest.rw.Code)
1401 assert.Equal(t, http.StatusAccepted, pcTest.rw.Code)
1363 assert.Equal(t, "oauth_user", pcTest.rw.Header().Get("X-Auth-Request-User"))
1402 assert.Equal(t, "oauth_user", pcTest.rw.Header().Get("X-Auth-Request-User"))
1403+ assert.Equal(t, startSession.Groups, pcTest.rw.Header().Values("X-Auth-Request-Groups"))
1364 assert.Equal(t, "oauth_user@example.com", pcTest.rw.Header().Get("X-Auth-Request-Email"))
1404 assert.Equal(t, "oauth_user@example.com", pcTest.rw.Header().Get("X-Auth-Request-Email"))
@@ -2199,3 +2239,108 @@ func TestTrustedIPs(t *testing.T) {
2243+func TestProxyAllowedGroups(t *testing.T) {
2244+ tests := []struct {
2246+ allowedGroups []string
2248+ expectUnauthorized bool
2250+ {"NoAllowedGroups", []string{}, []string{}, false},
2251+ {"NoAllowedGroupsUserHasGroups", []string{}, []string{"a", "b"}, false},
2252+ {"UserInAllowedGroup", []string{"a"}, []string{"a", "b"}, false},
2253+ {"UserNotInAllowedGroup", []string{"a"}, []string{"c"}, true},
2256+ for _, tt := range tests {
2257+ t.Run(tt.name, func(t *testing.T) {
2258+ emailAddress := "test"
2259+ created := time.Now()
2261+ session := &sessions.SessionState{
2263+ Email: emailAddress,
2264+ AccessToken: "oauth_token",
2265+ CreatedAt: &created,
2268+ upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
2271+ t.Cleanup(upstream.Close)
2273+ test, err := NewProcessCookieTestWithOptionsModifiers(func(opts *options.Options) {
2274+ opts.AllowedGroups = tt.allowedGroups
2275+ opts.UpstreamServers = options.Upstreams{
2287+ test.req, _ = http.NewRequest("GET", "/", nil)
2289+ test.req.Header.Add("accept", applicationJSON)
2290+ test.SaveSession(session)
2291+ test.proxy.ServeHTTP(test.rw, test.req)
2293+ if tt.expectUnauthorized {
2294+ assert.Equal(t, http.StatusUnauthorized, test.rw.Code)
2296+ assert.Equal(t, http.StatusOK, test.rw.Code)
2302+func TestAuthOnlyAllowedGroups(t *testing.T) {
2303+ tests := []struct {
2305+ allowedGroups []string
2307+ expectUnauthorized bool
2309+ {"NoAllowedGroups", []string{}, []string{}, false},
2310+ {"NoAllowedGroupsUserHasGroups", []string{}, []string{"a", "b"}, false},
2311+ {"UserInAllowedGroup", []string{"a"}, []string{"a", "b"}, false},
2312+ {"UserNotInAllowedGroup", []string{"a"}, []string{"c"}, true},
2315+ for _, tt := range tests {
2316+ t.Run(tt.name, func(t *testing.T) {
2317+ emailAddress := "test"
2318+ created := time.Now()
2320+ session := &sessions.SessionState{
2322+ Email: emailAddress,
2323+ AccessToken: "oauth_token",
2324+ CreatedAt: &created,
2327+ test, err := NewAuthOnlyEndpointTest(func(opts *options.Options) {
2328+ opts.AllowedGroups = tt.allowedGroups
2334+ err = test.SaveSession(session)
2335+ assert.NoError(t, err)
2337+ test.proxy.ServeHTTP(test.rw, test.req)
2339+ if tt.expectUnauthorized {
2340+ assert.Equal(t, http.StatusUnauthorized, test.rw.Code)
2342+ assert.Equal(t, http.StatusAccepted, test.rw.Code)