diff --git a/auth/basic/README.md b/auth/basic/README.md index 9e77c0f..fe3a9de 100644 --- a/auth/basic/README.md +++ b/auth/basic/README.md @@ -1,4 +1,4 @@ -`package auth/basic` provides a basic auth middleware [Mozilla article](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) +`package auth/basic` provides a Basic Authentication middleware [Mozilla article](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication). ## Usage @@ -13,4 +13,4 @@ ) ``` -For AuthMiddleware to be able to pick up Authentication header from a http request we need to pass it through the context with something like ```httptransport.ServerBefore(httptransport.PopulateRequestContext)``` \ No newline at end of file +For AuthMiddleware to be able to pick up the Authentication header from a HTTP request we need to pass it through the context with something like ```httptransport.ServerBefore(httptransport.PopulateRequestContext)```. \ No newline at end of file diff --git a/auth/basic/middleware.go b/auth/basic/middleware.go index 1f603de..17b0b61 100644 --- a/auth/basic/middleware.go +++ b/auth/basic/middleware.go @@ -1,6 +1,7 @@ package basic import ( + "bytes" "context" "crypto/sha256" "crypto/subtle" @@ -13,22 +14,22 @@ httptransport "github.com/go-kit/kit/transport/http" ) -// AuthError represents generic Authorization error +// AuthError represents an authoriation error. type AuthError struct { Realm string } -// StatusCode is an implemntation of StatusCoder interface in go-kit/http +// StatusCode is an iimplementation of the StatusCoder interface in go-kit/http. func (AuthError) StatusCode() int { return http.StatusUnauthorized } -// Error is an implemntation of Error interface +// Error is an implementation of the Error interface. func (AuthError) Error() string { return http.StatusText(http.StatusUnauthorized) } -// Headers is an implemntation of Headerer interface in go-kit/http +// Headers is an implemntation of the Headerer interface in go-kit/http. func (e AuthError) Headers() http.Header { return http.Header{ "Content-Type": []string{"text/plain; charset=utf-8"}, @@ -36,26 +37,9 @@ "WWW-Authenticate": []string{fmt.Sprintf(`Basic realm=%q`, e.Realm)}} } -func credsAreValid(givenUser, givenPass, requiredUser, requiredPass string) bool { - // Equalize lengths of supplied and required credentials - // by hashing them - givenUserBytes := sha256.Sum256([]byte(givenUser)) - givenPassBytes := sha256.Sum256([]byte(givenPass)) - requiredUserBytes := sha256.Sum256([]byte(requiredUser)) - requiredPassBytes := sha256.Sum256([]byte(requiredPass)) - - // Compare the supplied credentials to those set in our options - if subtle.ConstantTimeCompare(givenUserBytes[:], requiredUserBytes[:]) == 1 && - subtle.ConstantTimeCompare(givenPassBytes[:], requiredPassBytes[:]) == 1 { - return true - } - - return false -} - // parseBasicAuth parses an HTTP Basic Authentication string. -// "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ("Aladdin", "open sesame", true). -func parseBasicAuth(auth string) (username, password string, ok bool) { +// "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ([]byte("Aladdin"), []byte("open sesame"), true). +func parseBasicAuth(auth string) (username, password []byte, ok bool) { const prefix = "Basic " if !strings.HasPrefix(auth, prefix) { return @@ -64,16 +48,19 @@ if err != nil { return } - cs := string(c) - s := strings.IndexByte(cs, ':') + + s := bytes.IndexByte(c, ':') if s < 0 { return } - return cs[:s], cs[s+1:], true + return c[:s], c[s+1:], true } -// AuthMiddleware returns a Basic Authentication middleware for a particular user and password +// AuthMiddleware returns a Basic Authentication middleware for a particular user and password. func AuthMiddleware(requiredUser, requiredPassword, realm string) endpoint.Middleware { + requiredUserBytes := sha256.Sum256([]byte(requiredUser)) + requiredPassBytes := sha256.Sum256([]byte(requiredPassword)) + return func(next endpoint.Endpoint) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { auth := ctx.Value(httptransport.ContextKeyRequestAuthorization).(string) @@ -82,7 +69,13 @@ return nil, AuthError{realm} } - if !credsAreValid(givenUser, givenPass, requiredUser, requiredPassword) { + // Equalize lengths of supplied and required credentials by hashing them. + givenUserBytes := sha256.Sum256(givenUser) + givenPassBytes := sha256.Sum256(givenPass) + + // Compare the supplied credentials to those set in our options. + if subtle.ConstantTimeCompare(givenUserBytes[:], requiredUserBytes[:]) == 0 || + subtle.ConstantTimeCompare(givenPassBytes[:], requiredPassBytes[:]) == 0 { return nil, AuthError{realm} }