Add support for setting groups on session when using basic auth (#1064)
* Add support for setting groups on session when using basic auth * Refactoring based on feedback * Attribution
This commit is contained in:
		
							parent
							
								
									d3147c3ab2
								
							
						
					
					
						commit
						220b3708fc
					
				|  | @ -8,6 +8,7 @@ | |||
| 
 | ||||
| ## Changes since v7.0.1 | ||||
| 
 | ||||
| - [#1064](https://github.com/oauth2-proxy/oauth2-proxy/pull/1064) Add support for setting groups on session when using basic auth (@stefansedich) | ||||
| - [#1056](https://github.com/oauth2-proxy/oauth2-proxy/pull/1056) Add option for custom logos on the sign in page (@JoelSpeed) | ||||
| - [#1054](https://github.com/oauth2-proxy/oauth2-proxy/pull/1054) Update to Go 1.16 (@JoelSpeed) | ||||
| - [#1052](https://github.com/oauth2-proxy/oauth2-proxy/pull/1052) Update golangci-lint to latest version (v1.36.0) (@JoelSpeed) | ||||
|  |  | |||
|  | @ -62,6 +62,7 @@ An example [oauth2-proxy.cfg](https://github.com/oauth2-proxy/oauth2-proxy/blob/ | |||
| | `--google-group` | string | restrict logins to members of this google group (may be given multiple times). | | | ||||
| | `--google-service-account-json` | string | the path to the service account json credentials | | | ||||
| | `--htpasswd-file` | string | additionally authenticate against a htpasswd file. Entries must be created with `htpasswd -B` for bcrypt encryption | | | ||||
| | `--htpasswd-user-group` | string \| list | the groups to be set on sessions for htpasswd users | | | ||||
| | `--http-address` | string | `[http://]<addr>:<port>` or `unix://<path>` to listen on for HTTP clients | `"127.0.0.1:4180"` | | ||||
| | `--https-address` | string | `<addr>:<port>` to listen on for HTTPS clients | `":443"` | | ||||
| | `--logging-compress` | bool | Should rotated log files be compressed using gzip | false | | ||||
|  |  | |||
|  | @ -277,7 +277,7 @@ func buildSessionChain(opts *options.Options, sessionStore sessionsapi.SessionSt | |||
| 	} | ||||
| 
 | ||||
| 	if validator != nil { | ||||
| 		chain = chain.Append(middleware.NewBasicAuthSessionLoader(validator)) | ||||
| 		chain = chain.Append(middleware.NewBasicAuthSessionLoader(validator, opts.HtpasswdUserGroups)) | ||||
| 	} | ||||
| 
 | ||||
| 	chain = chain.Append(middleware.NewStoredSessionLoader(&middleware.StoredSessionLoaderOptions{ | ||||
|  |  | |||
|  | @ -54,6 +54,7 @@ type Options struct { | |||
| 	GoogleAdminEmail         string   `flag:"google-admin-email" cfg:"google_admin_email"` | ||||
| 	GoogleServiceAccountJSON string   `flag:"google-service-account-json" cfg:"google_service_account_json"` | ||||
| 	HtpasswdFile             string   `flag:"htpasswd-file" cfg:"htpasswd_file"` | ||||
| 	HtpasswdUserGroups       []string `flag:"htpasswd-user-group" cfg:"htpasswd_user_groups"` | ||||
| 
 | ||||
| 	Cookie    Cookie         `cfg:",squash"` | ||||
| 	Session   SessionOptions `cfg:",squash"` | ||||
|  | @ -199,6 +200,7 @@ func NewFlagSet() *pflag.FlagSet { | |||
| 	flagSet.String("client-secret-file", "", "the file with OAuth Client Secret") | ||||
| 	flagSet.String("authenticated-emails-file", "", "authenticate against emails via file (one per line)") | ||||
| 	flagSet.String("htpasswd-file", "", "additionally authenticate against a htpasswd file. Entries must be created with \"htpasswd -B\" for bcrypt encryption") | ||||
| 	flagSet.StringSlice("htpasswd-user-group", []string{}, "the groups to be set on sessions for htpasswd users (may be given multiple times)") | ||||
| 	flagSet.String("proxy-prefix", "/oauth2", "the url root path that this proxy should be nested under (e.g. /<oauth2>/sign_in)") | ||||
| 	flagSet.String("ping-path", "/ping", "the ping endpoint that can be used for basic health checks") | ||||
| 	flagSet.String("ping-user-agent", "", "special User-Agent that will be used for basic health checks") | ||||
|  |  | |||
|  | @ -11,9 +11,9 @@ import ( | |||
| 	"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger" | ||||
| ) | ||||
| 
 | ||||
| func NewBasicAuthSessionLoader(validator basic.Validator) alice.Constructor { | ||||
| func NewBasicAuthSessionLoader(validator basic.Validator, sessionGroups []string) alice.Constructor { | ||||
| 	return func(next http.Handler) http.Handler { | ||||
| 		return loadBasicAuthSession(validator, next) | ||||
| 		return loadBasicAuthSession(validator, sessionGroups, next) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -22,7 +22,7 @@ func NewBasicAuthSessionLoader(validator basic.Validator) alice.Constructor { | |||
| // If no authorization header is found, or the header is invalid, no session
 | ||||
| // will be loaded and the request will be passed to the next handler.
 | ||||
| // If a session was loaded by a previous handler, it will not be replaced.
 | ||||
| func loadBasicAuthSession(validator basic.Validator, next http.Handler) http.Handler { | ||||
| func loadBasicAuthSession(validator basic.Validator, sessionGroups []string, next http.Handler) http.Handler { | ||||
| 	return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { | ||||
| 		scope := middlewareapi.GetRequestScope(req) | ||||
| 		// If scope is nil, this will panic.
 | ||||
|  | @ -33,7 +33,7 @@ func loadBasicAuthSession(validator basic.Validator, next http.Handler) http.Han | |||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		session, err := getBasicSession(validator, req) | ||||
| 		session, err := getBasicSession(validator, sessionGroups, req) | ||||
| 		if err != nil { | ||||
| 			logger.Errorf("Error retrieving session from token in Authorization header: %v", err) | ||||
| 		} | ||||
|  | @ -47,7 +47,7 @@ func loadBasicAuthSession(validator basic.Validator, next http.Handler) http.Han | |||
| // getBasicSession attempts to load a basic session from the request.
 | ||||
| // If the credentials in the request exist within the htpasswdMap,
 | ||||
| // a new session will be created.
 | ||||
| func getBasicSession(validator basic.Validator, req *http.Request) (*sessionsapi.SessionState, error) { | ||||
| func getBasicSession(validator basic.Validator, sessionGroups []string, req *http.Request) (*sessionsapi.SessionState, error) { | ||||
| 	auth := req.Header.Get("Authorization") | ||||
| 	if auth == "" { | ||||
| 		// No auth header provided, so don't attempt to load a session
 | ||||
|  | @ -61,7 +61,8 @@ func getBasicSession(validator basic.Validator, req *http.Request) (*sessionsapi | |||
| 
 | ||||
| 	if validator.Validate(user, password) { | ||||
| 		logger.PrintAuthf(user, req, logger.AuthSuccess, "Authenticated via basic auth and HTpasswd File") | ||||
| 		return &sessionsapi.SessionState{User: user}, nil | ||||
| 
 | ||||
| 		return &sessionsapi.SessionState{User: user, Groups: sessionGroups}, nil | ||||
| 	} | ||||
| 
 | ||||
| 	logger.PrintAuthf(user, req, logger.AuthFailure, "Invalid authentication via basic auth: not in Htpasswd File") | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ var _ = Describe("Basic Auth Session Suite", func() { | |||
| 
 | ||||
| 		type basicAuthSessionLoaderTableInput struct { | ||||
| 			authorizationHeader string | ||||
| 			sessionGroups       []string | ||||
| 			existingSession     *sessionsapi.SessionState | ||||
| 			expectedSession     *sessionsapi.SessionState | ||||
| 		} | ||||
|  | @ -54,7 +55,7 @@ var _ = Describe("Basic Auth Session Suite", func() { | |||
| 				// Create the handler with a next handler that will capture the session
 | ||||
| 				// from the scope
 | ||||
| 				var gotSession *sessionsapi.SessionState | ||||
| 				handler := NewBasicAuthSessionLoader(validator)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| 				handler := NewBasicAuthSessionLoader(validator, in.sessionGroups)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| 					gotSession = middlewareapi.GetRequestScope(r).Session | ||||
| 				})) | ||||
| 				handler.ServeHTTP(rw, req) | ||||
|  | @ -111,6 +112,12 @@ var _ = Describe("Basic Auth Session Suite", func() { | |||
| 				existingSession:     nil, | ||||
| 				expectedSession:     &sessionsapi.SessionState{User: "admin"}, | ||||
| 			}), | ||||
| 			Entry("Basic with groups", basicAuthSessionLoaderTableInput{ | ||||
| 				authorizationHeader: "Basic YWRtaW46QWRtMW4xc3RyJHQwcg==", | ||||
| 				sessionGroups:       []string{"a", "b"}, | ||||
| 				existingSession:     nil, | ||||
| 				expectedSession:     &sessionsapi.SessionState{User: "admin", Groups: []string{"a", "b"}}, | ||||
| 			}), | ||||
| 		) | ||||
| 	}) | ||||
| }) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue