@@ -229,8 +229,9 @@ func TestIsValidRedirect(t *testing.T) {
230type TestProvider struct {
230type TestProvider struct {
231 *providers.ProviderData
231 *providers.ProviderData
232− EmailAddress string
232+ EmailAddress string
233− ValidToken bool
233+ ValidToken bool
234+ GroupValidator func(string) bool
236func NewTestProvider(providerURL *url.URL, emailAddress string) *TestProvider {
237func NewTestProvider(providerURL *url.URL, emailAddress string) *TestProvider {
@@ -255,6 +256,9 @@ func NewTestProvider(providerURL *url.URL, emailAddress string) *TestProvider {
255 Scope: "profile.email",
256 Scope: "profile.email",
257 EmailAddress: emailAddress,
258 EmailAddress: emailAddress,
259+ GroupValidator: func(s string) bool {
@@ -266,6 +270,13 @@ func (tp *TestProvider) ValidateSessionState(session *sessions.SessionState) boo
266 return tp.ValidToken
270 return tp.ValidToken
273+func (tp *TestProvider) ValidateGroup(email string) bool {
274+ if tp.GroupValidator != nil {
275+ return tp.GroupValidator(email)
269func TestBasicAuthPassword(t *testing.T) {
280func TestBasicAuthPassword(t *testing.T) {
270 providerServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
281 providerServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
271 logger.Printf("%#v", r)
282 logger.Printf("%#v", r)
@@ -791,6 +802,25 @@ func TestAuthOnlyEndpointUnauthorizedOnEmailValidationFailure(t *testing.T) {
791 assert.Equal(t, "unauthorized request\n", string(bodyBytes))
802 assert.Equal(t, "unauthorized request\n", string(bodyBytes))
805+func TestAuthOnlyEndpointUnauthorizedOnProviderGroupValidationFailure(t *testing.T) {
806+ test := NewAuthOnlyEndpointTest()
807+ startSession := &sessions.SessionState{
808+ Email: "michael.bland@gsa.gov", AccessToken: "my_access_token", CreatedAt: time.Now()}
809+ test.SaveSession(startSession)
810+ provider := &TestProvider{
812+ GroupValidator: func(s string) bool {
817+ test.proxy.provider = provider
818+ test.proxy.ServeHTTP(test.rw, test.req)
819+ assert.Equal(t, http.StatusUnauthorized, test.rw.Code)
820+ bodyBytes, _ := ioutil.ReadAll(test.rw.Body)
821+ assert.Equal(t, "unauthorized request\n", string(bodyBytes))
794func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) {
824func TestAuthOnlyEndpointSetXAuthRequestHeaders(t *testing.T) {
795 var pcTest ProcessCookieTest
825 var pcTest ProcessCookieTest
@@ -1168,69 +1198,80 @@ func TestGetJwtSession(t *testing.T) {
1168 keyset := NoOpKeySet{}
1198 keyset := NoOpKeySet{}
1169 verifier := oidc.NewVerifier("https://issuer.example.com", keyset,
1199 verifier := oidc.NewVerifier("https://issuer.example.com", keyset,
1170 &oidc.Config{ClientID: "https://test.myapp.com", SkipExpiryCheck: true})
1200 &oidc.Config{ClientID: "https://test.myapp.com", SkipExpiryCheck: true})
1172− p.jwtBearerVerifiers = append(p.jwtBearerVerifiers, verifier)
1174− req, _ := http.NewRequest("GET", "/", strings.NewReader(""))
1202+ test := NewAuthOnlyEndpointTest(func(opts *Options) {
1203+ opts.PassAuthorization = true
1204+ opts.SetAuthorization = true
1205+ opts.SetXAuthRequest = true
1206+ opts.SkipJwtBearerTokens = true
1207+ opts.jwtBearerVerifiers = append(opts.jwtBearerVerifiers, verifier)
1209+ tp, _ := test.proxy.provider.(*TestProvider)
1210+ tp.GroupValidator = func(s string) bool {
1175 authHeader := fmt.Sprintf("Bearer %s", goodJwt)
1214 authHeader := fmt.Sprintf("Bearer %s", goodJwt)
1176− req.Header = map[string][]string{
1215+ test.req.Header = map[string][]string{
1177 "Authorization": {authHeader},
1216 "Authorization": {authHeader},
1180 // Bearer
1219 // Bearer
1181− session, _ := p.GetJwtSession(req)
1220+ session, _ := test.proxy.GetJwtSession(test.req)
1182 assert.Equal(t, session.User, "john@example.com")
1221 assert.Equal(t, session.User, "john@example.com")
1183 assert.Equal(t, session.Email, "john@example.com")
1222 assert.Equal(t, session.Email, "john@example.com")
1184 assert.Equal(t, session.ExpiresOn, time.Unix(1912151821, 0))
1223 assert.Equal(t, session.ExpiresOn, time.Unix(1912151821, 0))
1185 assert.Equal(t, session.IDToken, goodJwt)
1224 assert.Equal(t, session.IDToken, goodJwt)
1187− jwtProviderServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1226+ test.proxy.ServeHTTP(test.rw, test.req)
1188− logger.Printf("%#v", r)
1227+ if test.rw.Code >= 400 {
1189− var payload string
1228+ t.Fatalf("expected 3xx got %d", test.rw.Code)
1190− payload = r.Header.Get("Authorization")
1192− payload = "No Authorization header found."
1195− w.Write([]byte(payload))
1198− opts := NewOptions()
1199− opts.Upstreams = append(opts.Upstreams, jwtProviderServer.URL)
1200− opts.PassAuthorization = true
1231+ // Check PassAuthorization, should overwrite Basic header
1201− opts.SetAuthorization = true
1232+ assert.Equal(t, test.req.Header.Get("Authorization"), authHeader)
1202− opts.SetXAuthRequest = true
1233+ assert.Equal(t, test.req.Header.Get("X-Forwarded-User"), "john@example.com")
1203− opts.CookieSecret = "0123456789abcdef0123"
1234+ assert.Equal(t, test.req.Header.Get("X-Forwarded-Email"), "john@example.com")
1204− opts.SkipJwtBearerTokens = true
1207− // We can't actually use opts.Validate() because it will attempt to find a jwks URI
1236+ // SetAuthorization and SetXAuthRequest
1208− opts.jwtBearerVerifiers = append(opts.jwtBearerVerifiers, verifier)
1237+ assert.Equal(t, test.rw.Header().Get("Authorization"), authHeader)
1238+ assert.Equal(t, test.rw.Header().Get("X-Auth-Request-User"), "john@example.com")
1239+ assert.Equal(t, test.rw.Header().Get("X-Auth-Request-Email"), "john@example.com")
1210− providerURL, _ := url.Parse(jwtProviderServer.URL)
1242+func TestJwtUnauthorizedOnGroupValidationFailure(t *testing.T) {
1211− const emailAddress = "john@example.com"
1243+ goodJwt := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9." +
1244+ "eyJzdWIiOiIxMjM0NTY3ODkwIiwiYXVkIjoiaHR0cHM6Ly90ZXN0Lm15YXBwLmNvbSIsIm5hbWUiOiJKb2huIERvZSIsImVtY" +
1245+ "WlsIjoiam9obkBleGFtcGxlLmNvbSIsImlzcyI6Imh0dHBzOi8vaXNzdWVyLmV4YW1wbGUuY29tIiwiaWF0IjoxNTUzNjkxMj" +
1246+ "E1LCJleHAiOjE5MTIxNTE4MjF9." +
1247+ "rLVyzOnEldUq_pNkfa-WiV8TVJYWyZCaM2Am_uo8FGg11zD7l-qmz3x1seTvqpH6Y0Ty00fmv6dJnGnC8WMnPXQiodRTfhBSe" +
1248+ "OKZMu0HkMD2sg52zlKkbfLTO6ic5VnbVgwjjrB8am_Ta6w7kyFUaB5C1BsIrrLMldkWEhynbb8"
1213− opts.provider = NewTestProvider(providerURL, emailAddress)
1250+ keyset := NoOpKeySet{}
1214− jwtTestProxy := NewOAuthProxy(opts, func(email string) bool {
1251+ verifier := oidc.NewVerifier("https://issuer.example.com", keyset,
1215− return email == emailAddress
1252+ &oidc.Config{ClientID: "https://test.myapp.com", SkipExpiryCheck: true})
1218− rw := httptest.NewRecorder()
1254+ test := NewAuthOnlyEndpointTest(func(opts *Options) {
1219− jwtTestProxy.ServeHTTP(rw, req)
1255+ opts.PassAuthorization = true
1220− if rw.Code >= 400 {
1256+ opts.SetAuthorization = true
1221− t.Fatalf("expected 3xx got %d", rw.Code)
1257+ opts.SetXAuthRequest = true
1258+ opts.SkipJwtBearerTokens = true
1259+ opts.jwtBearerVerifiers = append(opts.jwtBearerVerifiers, verifier)
1261+ tp, _ := test.proxy.provider.(*TestProvider)
1262+ // Verify ValidateGroup fails JWT authorization
1263+ tp.GroupValidator = func(s string) bool {
1224− // Check PassAuthorization, should overwrite Basic header
1267+ authHeader := fmt.Sprintf("Bearer %s", goodJwt)
1225− assert.Equal(t, req.Header.Get("Authorization"), authHeader)
1268+ test.req.Header = map[string][]string{
1226− assert.Equal(t, req.Header.Get("X-Forwarded-User"), "john@example.com")
1269+ "Authorization": {authHeader},
1227− assert.Equal(t, req.Header.Get("X-Forwarded-Email"), "john@example.com")
1270+ }
1228−
1271+ test.proxy.ServeHTTP(test.rw, test.req)
1229− // SetAuthorization and SetXAuthRequest
1272+ if test.rw.Code != http.StatusUnauthorized {
1230− assert.Equal(t, rw.Header().Get("Authorization"), authHeader)
1273+ t.Fatalf("expected 401 got %d", test.rw.Code)
1231− assert.Equal(t, rw.Header().Get("X-Auth-Request-User"), "john@example.com")
1274+ }
1232− assert.Equal(t, rw.Header().Get("X-Auth-Request-Email"), "john@example.com")
1236func TestFindJwtBearerToken(t *testing.T) {
1277func TestFindJwtBearerToken(t *testing.T) {