1
0
mirror of https://github.com/golang/go synced 2024-09-30 04:24:29 -06:00

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
This commit is contained in:
Alberto García Hierro 2013-05-14 15:33:46 -07:00 committed by Brad Fitzpatrick
parent 55c14fde8a
commit d535bc7af3
2 changed files with 47 additions and 1 deletions

View File

@ -161,7 +161,18 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) {
}
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)
if err != nil {

View File

@ -10,6 +10,7 @@ import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"errors"
"fmt"
"io"
@ -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()
}