diff --git a/httpbin/handlers.go b/httpbin/handlers.go
index 25fd90073d872befe8194f6d76dd32b57481e677..2073654f633baafd9ee65202af9fcd18151019dc 100644
--- a/httpbin/handlers.go
+++ b/httpbin/handlers.go
@@ -284,3 +284,28 @@ func (h *HTTPBin) DeleteCookies(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Location", "/cookies")
 	w.WriteHeader(http.StatusFound)
 }
+
+// BasicAuth requires basic authentication
+func (h *HTTPBin) BasicAuth(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()
+
+	status := http.StatusOK
+	authorized := givenUser == expectedUser && givenPass == expectedPass
+	if !authorized {
+		status = http.StatusUnauthorized
+	}
+
+	body, _ := json.Marshal(&authResponse{
+		Authorized: authorized,
+		User:       givenUser,
+	})
+	writeJSON(w, body, status)
+}
diff --git a/httpbin/handlers_test.go b/httpbin/handlers_test.go
index 97b87cc1706315c9f0580ce0fa54ff7164cafb68..4f87bc1f754b31714c28f8fb421ce51d150d11f7 100644
--- a/httpbin/handlers_test.go
+++ b/httpbin/handlers_test.go
@@ -908,3 +908,85 @@ func TestDeleteCookies(t *testing.T) {
 		}
 	}
 }
+
+func TestBasicAuth(t *testing.T) {
+	t.Run("ok", func(t *testing.T) {
+		r, _ := http.NewRequest("GET", "/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", "/basic-auth/user/pass", nil)
+		w := httptest.NewRecorder()
+		handler.ServeHTTP(w, r)
+
+		assertStatusCode(t, w, http.StatusUnauthorized)
+		assertContentType(t, w, jsonContentType)
+
+		resp := &authResponse{}
+		json.Unmarshal(w.Body.Bytes(), resp)
+
+		expectedResp := &authResponse{
+			Authorized: false,
+			User:       "",
+		}
+		if !reflect.DeepEqual(resp, expectedResp) {
+			t.Fatalf("expected response %#v, got %#v", expectedResp, resp)
+		}
+	})
+
+	t.Run("error/bad auth", func(t *testing.T) {
+		r, _ := http.NewRequest("GET", "/basic-auth/user/pass", nil)
+		r.SetBasicAuth("bad", "auth")
+		w := httptest.NewRecorder()
+		handler.ServeHTTP(w, r)
+
+		assertStatusCode(t, w, http.StatusUnauthorized)
+		assertContentType(t, w, jsonContentType)
+
+		resp := &authResponse{}
+		json.Unmarshal(w.Body.Bytes(), resp)
+
+		expectedResp := &authResponse{
+			Authorized: false,
+			User:       "bad",
+		}
+		if !reflect.DeepEqual(resp, expectedResp) {
+			t.Fatalf("expected response %#v, got %#v", expectedResp, resp)
+		}
+	})
+
+	var errorTests = []struct {
+		url    string
+		status int
+	}{
+		{"/basic-auth", http.StatusNotFound},
+		{"/basic-auth/user", http.StatusNotFound},
+		{"/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 7576af150d693c3e748f31be69d2c6b3869a3656..fca0002d01b8789cb22fc4135349f483de3921b8 100644
--- a/httpbin/httpbin.go
+++ b/httpbin/httpbin.go
@@ -41,6 +41,11 @@ type bodyResponse struct {
 
 type cookiesResponse map[string]string
 
+type authResponse struct {
+	Authorized bool   `json:"authorized"`
+	User       string `json:"user"`
+}
+
 // Options are used to configure HTTPBin
 type Options struct {
 	MaxMemory int64
@@ -79,13 +84,16 @@ func (h *HTTPBin) Handler() http.Handler {
 	mux.HandleFunc("/cookies/set", h.SetCookies)
 	mux.HandleFunc("/cookies/delete", h.DeleteCookies)
 
+	mux.HandleFunc("/basic-auth/", h.BasicAuth)
+
 	// 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("/status", http.NotFound)
+	mux.HandleFunc("/absolute-redirect", http.NotFound)
+	mux.HandleFunc("/basic-auth", http.NotFound)
 	mux.HandleFunc("/redirect", http.NotFound)
 	mux.HandleFunc("/relative-redirect", http.NotFound)
-	mux.HandleFunc("/absolute-redirect", http.NotFound)
+	mux.HandleFunc("/status", http.NotFound)
 
 	return logger(cors(mux))
 }