git.iko.soy/typeable/oauth2-proxy
on master help sign in
Merge pull request #32 from ccojocar/ajax_401

Returns HTTP unauthorized for ajax requests instead of redirecting to the sign-in page

commitb5b0633e0b6e2868f82900613bfe2035ef17250b authorJoel Speed <Joel.speed@hotmail.co.uk> dateThu 31 Jan 2019, 15:56 (8 years ago) parent01c5f5a3326194
2 files changed+94
oauthproxy.go+30 oauthproxy_test.go+64
oauthproxy.go+30
@@ -30,6 +30,8 @@ const (
3030 // Cookies are limited to 4kb including the length of the cookie name,
3131 // the cookie name can be up to 256 bytes
3232 maxCookieLength = 3840
33+
34+ applicationJSON = "application/json"
3335)
3436
3537// SignatureHeaders contains the headers to be signed by the hmac algorithm
@@ -754,6 +756,8 @@ func (p *OAuthProxy) Proxy(rw http.ResponseWriter, req *http.Request) {
754756 } else {
755757 p.SignInPage(rw, req, http.StatusForbidden)
756758 }
759+ } else if status == http.StatusUnauthorized {
760+ p.ErrorJSON(rw, status)
757761 } else {
758762 p.serveMux.ServeHTTP(rw, req)
759763 }
@@ -826,6 +830,11 @@ func (p *OAuthProxy) Authenticate(rw http.ResponseWriter, req *http.Request) int
826830 }
827831
828832 if session == nil {
833+ // Check if is an ajax request and return unauthorized to avoid a redirect
834+ // to the login page
835+ if p.isAjax(req) {
836+ return http.StatusUnauthorized
837+ }
829838 return http.StatusForbidden
830839 }
831840
@@ -894,3 +903,24 @@ func (p *OAuthProxy) CheckBasicAuth(req *http.Request) (*providers.SessionState,
894903 }
895904 return nil, fmt.Errorf("%s not in HtpasswdFile", pair[0])
896905}
906+
907+// isAjax checks if a request is an ajax request
908+func (p *OAuthProxy) isAjax(req *http.Request) bool {
909+ acceptValues, ok := req.Header["accept"]
910+ if !ok {
911+ acceptValues = req.Header["Accept"]
912+ }
913+ const ajaxReq = applicationJSON
914+ for _, v := range acceptValues {
915+ if v == ajaxReq {
916+ return true
917+ }
918+ }
919+ return false
920+}
921+
922+// ErrorJSON returns the error code witht an application/json mime type
923+func (p *OAuthProxy) ErrorJSON(rw http.ResponseWriter, code int) {
924+ rw.Header().Set("Content-Type", applicationJSON)
925+ rw.WriteHeader(code)
926+}
oauthproxy_test.go+64
@@ -871,3 +871,67 @@ func TestGetRedirect(t *testing.T) {
871871 })
872872 }
873873}
874+
875+type ajaxRequestTest struct {
876+ opts *Options
877+ proxy *OAuthProxy
878+}
879+
880+func newAjaxRequestTest() *ajaxRequestTest {
881+ test := &ajaxRequestTest{}
882+ test.opts = NewOptions()
883+ test.opts.CookieSecret = "foobar"
884+ test.opts.ClientID = "bazquux"
885+ test.opts.ClientSecret = "xyzzyplugh"
886+ test.opts.Validate()
887+ test.proxy = NewOAuthProxy(test.opts, func(email string) bool {
888+ return true
889+ })
890+ return test
891+}
892+
893+func (test *ajaxRequestTest) getEndpoint(endpoint string, header http.Header) (int, http.Header, error) {
894+ rw := httptest.NewRecorder()
895+ req, err := http.NewRequest(http.MethodGet, endpoint, strings.NewReader(""))
896+ if err != nil {
897+ return 0, nil, err
898+ }
899+ req.Header = header
900+ test.proxy.ServeHTTP(rw, req)
901+ return rw.Code, rw.Header(), nil
902+}
903+
904+func testAjaxUnauthorizedRequest(t *testing.T, header http.Header) {
905+ test := newAjaxRequestTest()
906+ endpoint := "/test"
907+
908+ code, rh, err := test.getEndpoint(endpoint, header)
909+ assert.NoError(t, err)
910+ assert.Equal(t, http.StatusUnauthorized, code)
911+ mime := rh.Get("Content-Type")
912+ assert.Equal(t, applicationJSON, mime)
913+}
914+func TestAjaxUnauthorizedRequest1(t *testing.T) {
915+ header := make(http.Header)
916+ header.Add("accept", applicationJSON)
917+
918+ testAjaxUnauthorizedRequest(t, header)
919+}
920+
921+func TestAjaxUnauthorizedRequest2(t *testing.T) {
922+ header := make(http.Header)
923+ header.Add("Accept", applicationJSON)
924+
925+ testAjaxUnauthorizedRequest(t, header)
926+}
927+
928+func TestAjaxForbiddendRequest(t *testing.T) {
929+ test := newAjaxRequestTest()
930+ endpoint := "/test"
931+ header := make(http.Header)
932+ code, rh, err := test.getEndpoint(endpoint, header)
933+ assert.NoError(t, err)
934+ assert.Equal(t, http.StatusForbidden, code)
935+ mime := rh.Get("Content-Type")
936+ assert.NotEqual(t, applicationJSON, mime)
937+}