parent
							
								
									e6e2dbe459
								
							
						
					
					
						commit
						e61fc9e7a6
					
				|  | @ -249,6 +249,7 @@ OAuth2 Proxy responds directly to the following endpoints. All other endpoints w | ||||||
| * /oauth2/sign_in - the login page, which also doubles as a sign out page (it clears cookies) | * /oauth2/sign_in - the login page, which also doubles as a sign out page (it clears cookies) | ||||||
| * /oauth2/start - a URL that will redirect to start the OAuth cycle | * /oauth2/start - a URL that will redirect to start the OAuth cycle | ||||||
| * /oauth2/callback - the URL used at the end of the OAuth cycle. The oauth app will be configured with this as the callback url. | * /oauth2/callback - the URL used at the end of the OAuth cycle. The oauth app will be configured with this as the callback url. | ||||||
|  | * /oauth2/auth - only returns a 202 Accepted response or a 401 Unauthorized response; for use with the [Nginx `auth_request` directive](http://nginx.org/en/docs/http/ngx_http_auth_request_module.html) | ||||||
| 
 | 
 | ||||||
| ## Logging Format | ## Logging Format | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,6 +33,7 @@ type OAuthProxy struct { | ||||||
| 	SignInPath        string | 	SignInPath        string | ||||||
| 	OAuthStartPath    string | 	OAuthStartPath    string | ||||||
| 	OAuthCallbackPath string | 	OAuthCallbackPath string | ||||||
|  | 	AuthOnlyPath      string | ||||||
| 
 | 
 | ||||||
| 	redirectURL         *url.URL // the url to receive requests at
 | 	redirectURL         *url.URL // the url to receive requests at
 | ||||||
| 	provider            providers.Provider | 	provider            providers.Provider | ||||||
|  | @ -156,6 +157,7 @@ func NewOAuthProxy(opts *Options, validator func(string) bool) *OAuthProxy { | ||||||
| 		SignInPath:        fmt.Sprintf("%s/sign_in", opts.ProxyPrefix), | 		SignInPath:        fmt.Sprintf("%s/sign_in", opts.ProxyPrefix), | ||||||
| 		OAuthStartPath:    fmt.Sprintf("%s/start", opts.ProxyPrefix), | 		OAuthStartPath:    fmt.Sprintf("%s/start", opts.ProxyPrefix), | ||||||
| 		OAuthCallbackPath: fmt.Sprintf("%s/callback", opts.ProxyPrefix), | 		OAuthCallbackPath: fmt.Sprintf("%s/callback", opts.ProxyPrefix), | ||||||
|  | 		AuthOnlyPath:      fmt.Sprintf("%s/auth", opts.ProxyPrefix), | ||||||
| 
 | 
 | ||||||
| 		ProxyPrefix:       opts.ProxyPrefix, | 		ProxyPrefix:       opts.ProxyPrefix, | ||||||
| 		provider:          opts.provider, | 		provider:          opts.provider, | ||||||
|  | @ -390,6 +392,8 @@ func (p *OAuthProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { | ||||||
| 		p.OAuthStart(rw, req) | 		p.OAuthStart(rw, req) | ||||||
| 	case path == p.OAuthCallbackPath: | 	case path == p.OAuthCallbackPath: | ||||||
| 		p.OAuthCallback(rw, req) | 		p.OAuthCallback(rw, req) | ||||||
|  | 	case path == p.AuthOnlyPath: | ||||||
|  | 		p.AuthenticateOnly(rw, req) | ||||||
| 	default: | 	default: | ||||||
| 		p.Proxy(rw, req) | 		p.Proxy(rw, req) | ||||||
| 	} | 	} | ||||||
|  | @ -465,6 +469,21 @@ func (p *OAuthProxy) OAuthCallback(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (p *OAuthProxy) AuthenticateOnly(rw http.ResponseWriter, req *http.Request) { | ||||||
|  | 	remoteAddr := getRemoteAddr(req) | ||||||
|  | 	if session, _, err := p.LoadCookiedSession(req); err != nil { | ||||||
|  | 		log.Printf("%s %s", remoteAddr, err) | ||||||
|  | 	} else if session.IsExpired() { | ||||||
|  | 		log.Printf("%s Expired", remoteAddr, session) | ||||||
|  | 	} else if !p.Validator(session.Email) { | ||||||
|  | 		log.Printf("%s Permission Denied", remoteAddr, session) | ||||||
|  | 	} else { | ||||||
|  | 		rw.WriteHeader(http.StatusAccepted) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	http.Error(rw, "unauthorized request", http.StatusUnauthorized) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (p *OAuthProxy) Proxy(rw http.ResponseWriter, req *http.Request) { | func (p *OAuthProxy) Proxy(rw http.ResponseWriter, req *http.Request) { | ||||||
| 	var saveSession, clearSession, revalidated bool | 	var saveSession, clearSession, revalidated bool | ||||||
| 	remoteAddr := getRemoteAddr(req) | 	remoteAddr := getRemoteAddr(req) | ||||||
|  |  | ||||||
|  | @ -555,3 +555,58 @@ func TestProcessCookieFailIfRefreshSetAndCookieExpired(t *testing.T) { | ||||||
| 		t.Errorf("expected nil session %#v", session) | 		t.Errorf("expected nil session %#v", session) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func NewAuthOnlyEndpointTest() *ProcessCookieTest { | ||||||
|  | 	pc_test := NewProcessCookieTestWithDefaults() | ||||||
|  | 	pc_test.req, _ = http.NewRequest("GET", | ||||||
|  | 		pc_test.opts.ProxyPrefix + "/auth", nil) | ||||||
|  | 	return pc_test | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestAuthOnlyEndpointAccepted(t *testing.T) { | ||||||
|  | 	test := NewAuthOnlyEndpointTest() | ||||||
|  | 	startSession := &providers.SessionState{ | ||||||
|  | 		Email: "michael.bland@gsa.gov", AccessToken: "my_access_token"} | ||||||
|  | 	test.SaveSession(startSession, time.Now()) | ||||||
|  | 
 | ||||||
|  | 	test.proxy.ServeHTTP(test.rw, test.req) | ||||||
|  | 	assert.Equal(t, http.StatusAccepted, test.rw.Code) | ||||||
|  | 	bodyBytes, _ := ioutil.ReadAll(test.rw.Body) | ||||||
|  | 	assert.Equal(t, "", string(bodyBytes)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestAuthOnlyEndpointUnauthorizedOnNoCookieSetError(t *testing.T) { | ||||||
|  | 	test := NewAuthOnlyEndpointTest() | ||||||
|  | 
 | ||||||
|  | 	test.proxy.ServeHTTP(test.rw, test.req) | ||||||
|  | 	assert.Equal(t, http.StatusUnauthorized, test.rw.Code) | ||||||
|  | 	bodyBytes, _ := ioutil.ReadAll(test.rw.Body) | ||||||
|  | 	assert.Equal(t, "unauthorized request\n", string(bodyBytes)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestAuthOnlyEndpointUnauthorizedOnExpiration(t *testing.T) { | ||||||
|  | 	test := NewAuthOnlyEndpointTest() | ||||||
|  | 	test.proxy.CookieExpire = time.Duration(24) * time.Hour | ||||||
|  | 	reference := time.Now().Add(time.Duration(25) * time.Hour * -1) | ||||||
|  | 	startSession := &providers.SessionState{ | ||||||
|  | 		Email: "michael.bland@gsa.gov", AccessToken: "my_access_token"} | ||||||
|  | 	test.SaveSession(startSession, reference) | ||||||
|  | 
 | ||||||
|  | 	test.proxy.ServeHTTP(test.rw, test.req) | ||||||
|  | 	assert.Equal(t, http.StatusUnauthorized, test.rw.Code) | ||||||
|  | 	bodyBytes, _ := ioutil.ReadAll(test.rw.Body) | ||||||
|  | 	assert.Equal(t, "unauthorized request\n", string(bodyBytes)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestAuthOnlyEndpointUnauthorizedOnEmailValidationFailure(t *testing.T) { | ||||||
|  | 	test := NewAuthOnlyEndpointTest() | ||||||
|  | 	startSession := &providers.SessionState{ | ||||||
|  | 		Email: "michael.bland@gsa.gov", AccessToken: "my_access_token"} | ||||||
|  | 	test.SaveSession(startSession, time.Now()) | ||||||
|  | 	test.validate_user = false | ||||||
|  | 
 | ||||||
|  | 	test.proxy.ServeHTTP(test.rw, test.req) | ||||||
|  | 	assert.Equal(t, http.StatusUnauthorized, test.rw.Code) | ||||||
|  | 	bodyBytes, _ := ioutil.ReadAll(test.rw.Body) | ||||||
|  | 	assert.Equal(t, "unauthorized request\n", string(bodyBytes)) | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue