From ef7fd18e57d115351cff654d7bbe02965ee7dc0a Mon Sep 17 00:00:00 2001 From: Will McCutchen <will@mccutch.org> Date: Sat, 15 Oct 2016 16:50:36 -0700 Subject: [PATCH] Add /hidden-basic-auth/:user/:pass handler --- httpbin/handlers.go | 26 ++++++++++++++++ httpbin/handlers_test.go | 64 ++++++++++++++++++++++++++++++++++++++++ httpbin/httpbin.go | 2 ++ 3 files changed, 92 insertions(+) diff --git a/httpbin/handlers.go b/httpbin/handlers.go index 13754e6..d9e48d7 100644 --- a/httpbin/handlers.go +++ b/httpbin/handlers.go @@ -310,3 +310,29 @@ func (h *HTTPBin) BasicAuth(w http.ResponseWriter, r *http.Request) { }) writeJSON(w, body, status) } + +// HiddenBasicAuth requires HTTP Basic authentication but returns a status of +// 404 if the request is unauthorized +func (h *HTTPBin) HiddenBasicAuth(w http.ResponseWriter, r *http.Request) { + parts := strings.Split(r.URL.Path, "/") + if len(parts) != 4 { + http.Error(w, "Not Found", http.StatusNotFound) + return + } + expectedUser := parts[2] + expectedPass := parts[3] + + givenUser, givenPass, _ := r.BasicAuth() + + authorized := givenUser == expectedUser && givenPass == expectedPass + if !authorized { + http.Error(w, "Not Found", http.StatusNotFound) + return + } + + body, _ := json.Marshal(&authResponse{ + Authorized: authorized, + User: givenUser, + }) + writeJSON(w, body, http.StatusOK) +} diff --git a/httpbin/handlers_test.go b/httpbin/handlers_test.go index 6698bcb..721a417 100644 --- a/httpbin/handlers_test.go +++ b/httpbin/handlers_test.go @@ -992,3 +992,67 @@ func TestBasicAuth(t *testing.T) { }) } } + +func TestHiddenBasicAuth(t *testing.T) { + t.Run("ok", func(t *testing.T) { + r, _ := http.NewRequest("GET", "/hidden-basic-auth/user/pass", nil) + r.SetBasicAuth("user", "pass") + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + + assertStatusCode(t, w, http.StatusOK) + assertContentType(t, w, jsonContentType) + + resp := &authResponse{} + json.Unmarshal(w.Body.Bytes(), resp) + + expectedResp := &authResponse{ + Authorized: true, + User: "user", + } + if !reflect.DeepEqual(resp, expectedResp) { + t.Fatalf("expected response %#v, got %#v", expectedResp, resp) + } + }) + + t.Run("error/no auth", func(t *testing.T) { + r, _ := http.NewRequest("GET", "/hidden-basic-auth/user/pass", nil) + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + + assertStatusCode(t, w, http.StatusNotFound) + if w.Header().Get("WWW-Authenticate") != "" { + t.Fatal("did not expect WWW-Authenticate header") + } + }) + + t.Run("error/bad auth", func(t *testing.T) { + r, _ := http.NewRequest("GET", "/hidden-basic-auth/user/pass", nil) + r.SetBasicAuth("bad", "auth") + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + + assertStatusCode(t, w, http.StatusNotFound) + if w.Header().Get("WWW-Authenticate") != "" { + t.Fatal("did not expect WWW-Authenticate header") + } + }) + + var errorTests = []struct { + url string + status int + }{ + {"/hidden-basic-auth", http.StatusNotFound}, + {"/hidden-basic-auth/user", http.StatusNotFound}, + {"/hidden-basic-auth/user/pass/extra", http.StatusNotFound}, + } + for _, test := range errorTests { + t.Run("error"+test.url, func(t *testing.T) { + r, _ := http.NewRequest("GET", test.url, nil) + r.SetBasicAuth("foo", "bar") + w := httptest.NewRecorder() + handler.ServeHTTP(w, r) + assertStatusCode(t, w, test.status) + }) + } +} diff --git a/httpbin/httpbin.go b/httpbin/httpbin.go index fca0002..dd00375 100644 --- a/httpbin/httpbin.go +++ b/httpbin/httpbin.go @@ -85,12 +85,14 @@ func (h *HTTPBin) Handler() http.Handler { mux.HandleFunc("/cookies/delete", h.DeleteCookies) mux.HandleFunc("/basic-auth/", h.BasicAuth) + mux.HandleFunc("/hidden-basic-auth/", h.HiddenBasicAuth) // Make sure our ServeMux doesn't "helpfully" redirect these invalid // endpoints by adding a trailing slash. See the ServeMux docs for more // info: https://golang.org/pkg/net/http/#ServeMux mux.HandleFunc("/absolute-redirect", http.NotFound) mux.HandleFunc("/basic-auth", http.NotFound) + mux.HandleFunc("/hidden-basic-auth", http.NotFound) mux.HandleFunc("/redirect", http.NotFound) mux.HandleFunc("/relative-redirect", http.NotFound) mux.HandleFunc("/status", http.NotFound) -- GitLab