// HTTP request username is logged, but unused. Password is an
// Arvados API token.
- username, password, ok := r.BasicAuth()
+ username, password, ok := BasicAuth(r)
if !ok || username == "" || password == "" {
statusCode, statusText = http.StatusUnauthorized, "no credentials provided"
w.Header().Add("WWW-Authenticate", "basic")
--- /dev/null
+// +build !go1.4
+
+package main
+
+import (
+ "encoding/base64"
+ "net/http"
+ "strings"
+)
+
+func BasicAuth(r *http.Request) (username, password string, ok bool) {
+ toks := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
+ if len(toks) != 2 || toks[0] != "Basic" {
+ return "", "", false
+ }
+
+ decoded, err := base64.StdEncoding.DecodeString(toks[1])
+ if err != nil {
+ return "", "", false
+ }
+
+ userAndPass := strings.SplitN(string(decoded), ":", 2)
+ if len(userAndPass) != 2 {
+ return "", "", false
+ }
+
+ return userAndPass[0], userAndPass[1], true
+}
--- /dev/null
+package main
+
+import (
+ "net/http"
+ "testing"
+)
+
+type basicAuthTestCase struct {
+ hdr string
+ user string
+ pass string
+ ok bool
+}
+
+func TestBasicAuth(t *testing.T) {
+ tests := []basicAuthTestCase{
+ basicAuthTestCase{"Basic Zm9vOmJhcg==", "foo", "bar", true},
+ basicAuthTestCase{"Bogus Zm9vOmJhcg==", "", "", false},
+ basicAuthTestCase{"Zm9vOmJhcg==", "", "", false},
+ basicAuthTestCase{"Basic", "", "", false},
+ basicAuthTestCase{"", "", "", false},
+ }
+ for _, test := range tests {
+ if u, p, ok := BasicAuth(&http.Request{Header: map[string][]string{
+ "Authorization": []string{test.hdr},
+ }}); u != test.user || p != test.pass || ok != test.ok {
+ t.Error("got:", u, p, ok, "expected:", test.user, test.pass, test.ok, "from:", test.hdr)
+ }
+ }
+}