Commit d535bc7a authored by Alberto García Hierro's avatar Alberto García Hierro Committed by Brad Fitzpatrick

net/http: Fix basic authentication with empty password

        The encoded string must include the : separating the username
        and the password, even when the latter is empty. See
        http://www.ietf.org/rfc/rfc2617.txt for more information.

R=golang-dev, bradfitz, adg
CC=golang-dev
https://golang.org/cl/8475043
parent 55c14fde
...@@ -161,7 +161,18 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) { ...@@ -161,7 +161,18 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) {
} }
if u := req.URL.User; u != nil { if u := req.URL.User; u != nil {
req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(u.String()))) auth := u.String()
// UserInfo.String() only returns the colon when the
// password is set, so we must add it here.
//
// See 2 (end of page 4) http://www.ietf.org/rfc/rfc2617.txt
// "To receive authorization, the client sends the userid and password,
// separated by a single colon (":") character, within a base64
// encoded string in the credentials."
if _, hasPassword := u.Password(); !hasPassword {
auth += ":"
}
req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(auth)))
} }
resp, err = t.RoundTrip(req) resp, err = t.RoundTrip(req)
if err != nil { if err != nil {
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"bytes" "bytes"
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/base64"
"errors" "errors"
"fmt" "fmt"
"io" "io"
...@@ -700,3 +701,37 @@ func TestClientHeadContentLength(t *testing.T) { ...@@ -700,3 +701,37 @@ func TestClientHeadContentLength(t *testing.T) {
} }
} }
} }
func TestEmptyPasswordAuth(t *testing.T) {
defer afterTest(t)
gopher := "gopher"
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
auth := r.Header.Get("Authorization")
if strings.HasPrefix(auth, "Basic ") {
encoded := auth[6:]
decoded, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
t.Fatal(err)
}
expected := gopher + ":"
s := string(decoded)
if expected != s {
t.Errorf("Invalid Authorization header. Got %q, wanted %q", s, expected)
}
} else {
t.Errorf("Invalid auth %q", auth)
}
}))
defer ts.Close()
c := &Client{}
req, err := NewRequest("GET", ts.URL, nil)
if err != nil {
t.Fatal(err)
}
req.URL.User = url.User(gopher)
resp, err := c.Do(req)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment