13 | 13 |
httptransport "github.com/go-kit/kit/transport/http"
|
14 | 14 |
)
|
15 | 15 |
|
16 | |
// AuthError represents an authoriation error.
|
|
16 |
// AuthError represents an authorization error.
|
17 | 17 |
type AuthError struct {
|
18 | 18 |
Realm string
|
19 | 19 |
}
|
20 | 20 |
|
21 | |
// StatusCode is an iimplementation of the StatusCoder interface in go-kit/http.
|
|
21 |
// StatusCode is an implementation of the StatusCoder interface in go-kit/http.
|
22 | 22 |
func (AuthError) StatusCode() int {
|
23 | 23 |
return http.StatusUnauthorized
|
24 | 24 |
}
|
|
28 | 28 |
return http.StatusText(http.StatusUnauthorized)
|
29 | 29 |
}
|
30 | 30 |
|
31 | |
// Headers is an implemntation of the Headerer interface in go-kit/http.
|
|
31 |
// Headers is an implementation of the Headerer interface in go-kit/http.
|
32 | 32 |
func (e AuthError) Headers() http.Header {
|
33 | 33 |
return http.Header{
|
34 | 34 |
"Content-Type": []string{"text/plain; charset=utf-8"},
|
|
55 | 55 |
return c[:s], c[s+1:], true
|
56 | 56 |
}
|
57 | 57 |
|
|
58 |
// Returns a hash of a given slice.
|
|
59 |
func toHashSlice(s []byte) []byte {
|
|
60 |
hash := sha256.Sum256(s)
|
|
61 |
return hash[:]
|
|
62 |
}
|
|
63 |
|
58 | 64 |
// AuthMiddleware returns a Basic Authentication middleware for a particular user and password.
|
59 | 65 |
func AuthMiddleware(requiredUser, requiredPassword, realm string) endpoint.Middleware {
|
60 | |
requiredUserBytes := sha256.Sum256([]byte(requiredUser))
|
61 | |
requiredPassBytes := sha256.Sum256([]byte(requiredPassword))
|
|
66 |
requiredUserBytes := toHashSlice([]byte(requiredUser))
|
|
67 |
requiredPasswordBytes := toHashSlice([]byte(requiredPassword))
|
62 | 68 |
|
63 | 69 |
return func(next endpoint.Endpoint) endpoint.Endpoint {
|
64 | 70 |
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
65 | 71 |
auth := ctx.Value(httptransport.ContextKeyRequestAuthorization).(string)
|
66 | |
givenUser, givenPass, ok := parseBasicAuth(auth)
|
|
72 |
givenUser, givenPassword, ok := parseBasicAuth(auth)
|
67 | 73 |
if !ok {
|
68 | 74 |
return nil, AuthError{realm}
|
69 | 75 |
}
|
70 | 76 |
|
71 | 77 |
// Equalize lengths of supplied and required credentials by hashing them.
|
72 | |
givenUserBytes := sha256.Sum256(givenUser)
|
73 | |
givenPassBytes := sha256.Sum256(givenPass)
|
|
78 |
givenUserBytes := toHashSlice(givenUser)
|
|
79 |
givenPasswordBytes := toHashSlice(givenPassword)
|
74 | 80 |
|
75 | |
// Compare the supplied credentials to those set in our options.
|
76 | |
if subtle.ConstantTimeCompare(givenUserBytes[:], requiredUserBytes[:]) == 0 ||
|
77 | |
subtle.ConstantTimeCompare(givenPassBytes[:], requiredPassBytes[:]) == 0 {
|
|
81 |
if subtle.ConstantTimeCompare(givenUserBytes, requiredUserBytes) == 0 ||
|
|
82 |
subtle.ConstantTimeCompare(givenPasswordBytes, requiredPasswordBytes) == 0 {
|
78 | 83 |
return nil, AuthError{realm}
|
79 | 84 |
}
|
80 | 85 |
|