Add allowed_emails option to the auth endpoint query string (#1595)
* Add allowed_emails option to the auth endpoint query string * Don't return true from checkAllowedEmailsOrDomains only because domains field was empty * Fix checkAllowedEmailsOrDomains logic * Added tests for allowed_emails query parameter * Updated CHANGELOG * Remove checkAllowedEmailsOrDomains Co-authored-by: Nick Meves <nicholas.meves@gmail.com>
This commit is contained in:
		
							parent
							
								
									333e68637f
								
							
						
					
					
						commit
						b794248176
					
				|  | @ -18,6 +18,7 @@ If you are using an architecture specific tag (ex: v7.2.1-arm64) you should move | ||||||
| 
 | 
 | ||||||
| ## Changes since v7.2.1 | ## Changes since v7.2.1 | ||||||
| 
 | 
 | ||||||
|  | - [#1595](https://github.com/oauth2-proxy/oauth2-proxy/pull/1595) Add optional `allowed_emails` query parameter to the `auth_request`. (@zv0n) | ||||||
| - [#1478](https://github.com/oauth2-proxy/oauth2-proxy/pull/1478) Parameterise the runtime image (@omBratteng) | - [#1478](https://github.com/oauth2-proxy/oauth2-proxy/pull/1478) Parameterise the runtime image (@omBratteng) | ||||||
| - [#1583](https://github.com/oauth2-proxy/oauth2-proxy/pull/1583) Add groups to session too when creating session from bearer token (@adriananeci) | - [#1583](https://github.com/oauth2-proxy/oauth2-proxy/pull/1583) Add groups to session too when creating session from bearer token (@adriananeci) | ||||||
| - [#1418](https://github.com/oauth2-proxy/oauth2-proxy/pull/1418) Support for passing arbitrary query parameters through from `/oauth2/start` to the identity provider's login URL. Configuration settings control which parameters are passed by default and precisely which values can be overridden per-request (@ianroberts) | - [#1418](https://github.com/oauth2-proxy/oauth2-proxy/pull/1418) Support for passing arbitrary query parameters through from `/oauth2/start` to the identity provider's login URL. Configuration settings control which parameters are passed by default and precisely which values can be overridden per-request (@ianroberts) | ||||||
|  |  | ||||||
|  | @ -42,3 +42,4 @@ This endpoint returns 202 Accepted response or a 401 Unauthorized response. | ||||||
| It can be configured using the following query parameters query parameters: | It can be configured using the following query parameters query parameters: | ||||||
| - `allowed_groups`: comma separated list of allowed groups | - `allowed_groups`: comma separated list of allowed groups | ||||||
| - `allowed_email_domains`: comma separated list of allowed email domains | - `allowed_email_domains`: comma separated list of allowed email domains | ||||||
|  | - `allowed_emails`: comma separated list of allowed emails | ||||||
|  | @ -1021,6 +1021,7 @@ func authOnlyAuthorize(req *http.Request, s *sessionsapi.SessionState) bool { | ||||||
| 	constraints := []func(*http.Request, *sessionsapi.SessionState) bool{ | 	constraints := []func(*http.Request, *sessionsapi.SessionState) bool{ | ||||||
| 		checkAllowedGroups, | 		checkAllowedGroups, | ||||||
| 		checkAllowedEmailDomains, | 		checkAllowedEmailDomains, | ||||||
|  | 		checkAllowedEmails, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for _, constraint := range constraints { | 	for _, constraint := range constraints { | ||||||
|  | @ -1091,6 +1092,26 @@ func checkAllowedGroups(req *http.Request, s *sessionsapi.SessionState) bool { | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // checkAllowedEmails allow email restrictions based on the `allowed_emails`
 | ||||||
|  | // querystring parameter
 | ||||||
|  | func checkAllowedEmails(req *http.Request, s *sessionsapi.SessionState) bool { | ||||||
|  | 	allowedEmails := extractAllowedEntities(req, "allowed_emails") | ||||||
|  | 	if len(allowedEmails) == 0 { | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	allowed := false | ||||||
|  | 
 | ||||||
|  | 	for email := range allowedEmails { | ||||||
|  | 		if email == s.Email { | ||||||
|  | 			allowed = true | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return allowed | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // encodedState builds the OAuth state param out of our nonce and
 | // encodedState builds the OAuth state param out of our nonce and
 | ||||||
| // original application redirect
 | // original application redirect
 | ||||||
| func encodeState(nonce string, redirect string) string { | func encodeState(nonce string, redirect string) string { | ||||||
|  |  | ||||||
|  | @ -2725,7 +2725,7 @@ func TestAuthOnlyAllowedEmailDomains(t *testing.T) { | ||||||
| 			expectedStatusCode: http.StatusForbidden, | 			expectedStatusCode: http.StatusForbidden, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			name:               "UserInAllowedEmailDomains", | 			name:               "UserNotInAllowedEmailDomains", | ||||||
| 			email:              "toto@example.com", | 			email:              "toto@example.com", | ||||||
| 			querystring:        "?allowed_email_domains=a.example.com,b.example.com", | 			querystring:        "?allowed_email_domains=a.example.com,b.example.com", | ||||||
| 			expectedStatusCode: http.StatusForbidden, | 			expectedStatusCode: http.StatusForbidden, | ||||||
|  | @ -2789,3 +2789,70 @@ func TestAuthOnlyAllowedEmailDomains(t *testing.T) { | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestAuthOnlyAllowedEmails(t *testing.T) { | ||||||
|  | 	testCases := []struct { | ||||||
|  | 		name               string | ||||||
|  | 		email              string | ||||||
|  | 		querystring        string | ||||||
|  | 		expectedStatusCode int | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			name:               "NotEmailRestriction", | ||||||
|  | 			email:              "toto@example.com", | ||||||
|  | 			querystring:        "", | ||||||
|  | 			expectedStatusCode: http.StatusAccepted, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:               "UserInAllowedEmail", | ||||||
|  | 			email:              "toto@example.com", | ||||||
|  | 			querystring:        "?allowed_emails=toto@example.com", | ||||||
|  | 			expectedStatusCode: http.StatusAccepted, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:               "UserNotInAllowedEmail", | ||||||
|  | 			email:              "toto@example.com", | ||||||
|  | 			querystring:        "?allowed_emails=tete@example.com", | ||||||
|  | 			expectedStatusCode: http.StatusForbidden, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:               "UserNotInAllowedEmails", | ||||||
|  | 			email:              "toto@example.com", | ||||||
|  | 			querystring:        "?allowed_emails=tete@example.com,tutu@example.com", | ||||||
|  | 			expectedStatusCode: http.StatusForbidden, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:               "UserInAllowedEmails", | ||||||
|  | 			email:              "toto@example.com", | ||||||
|  | 			querystring:        "?allowed_emails=tete@example.com,toto@example.com", | ||||||
|  | 			expectedStatusCode: http.StatusAccepted, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, tc := range testCases { | ||||||
|  | 		t.Run(tc.name, func(t *testing.T) { | ||||||
|  | 			groups := []string{} | ||||||
|  | 
 | ||||||
|  | 			created := time.Now() | ||||||
|  | 
 | ||||||
|  | 			session := &sessions.SessionState{ | ||||||
|  | 				Groups:      groups, | ||||||
|  | 				Email:       tc.email, | ||||||
|  | 				AccessToken: "oauth_token", | ||||||
|  | 				CreatedAt:   &created, | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			test, err := NewAuthOnlyEndpointTest(tc.querystring, func(opts *options.Options) {}) | ||||||
|  | 			if err != nil { | ||||||
|  | 				t.Fatal(err) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			err = test.SaveSession(session) | ||||||
|  | 			assert.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 			test.proxy.ServeHTTP(test.rw, test.req) | ||||||
|  | 
 | ||||||
|  | 			assert.Equal(t, tc.expectedStatusCode, test.rw.Code) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue