OSDN Git Service

delete miner
[bytom/vapor.git] / vendor / github.com / go-kit / kit / auth / basic / middleware.go
1 package basic
2
3 import (
4         "bytes"
5         "context"
6         "crypto/sha256"
7         "crypto/subtle"
8         "encoding/base64"
9         "fmt"
10         "net/http"
11         "strings"
12
13         "github.com/go-kit/kit/endpoint"
14         httptransport "github.com/go-kit/kit/transport/http"
15 )
16
17 // AuthError represents an authorization error.
18 type AuthError struct {
19         Realm string
20 }
21
22 // StatusCode is an implementation of the StatusCoder interface in go-kit/http.
23 func (AuthError) StatusCode() int {
24         return http.StatusUnauthorized
25 }
26
27 // Error is an implementation of the Error interface.
28 func (AuthError) Error() string {
29         return http.StatusText(http.StatusUnauthorized)
30 }
31
32 // Headers is an implementation of the Headerer interface in go-kit/http.
33 func (e AuthError) Headers() http.Header {
34         return http.Header{
35                 "Content-Type":           []string{"text/plain; charset=utf-8"},
36                 "X-Content-Type-Options": []string{"nosniff"},
37                 "WWW-Authenticate":       []string{fmt.Sprintf(`Basic realm=%q`, e.Realm)},
38         }
39 }
40
41 // parseBasicAuth parses an HTTP Basic Authentication string.
42 // "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ([]byte("Aladdin"), []byte("open sesame"), true).
43 func parseBasicAuth(auth string) (username, password []byte, ok bool) {
44         const prefix = "Basic "
45         if !strings.HasPrefix(auth, prefix) {
46                 return
47         }
48         c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
49         if err != nil {
50                 return
51         }
52
53         s := bytes.IndexByte(c, ':')
54         if s < 0 {
55                 return
56         }
57         return c[:s], c[s+1:], true
58 }
59
60 // Returns a hash of a given slice.
61 func toHashSlice(s []byte) []byte {
62         hash := sha256.Sum256(s)
63         return hash[:]
64 }
65
66 // AuthMiddleware returns a Basic Authentication middleware for a particular user and password.
67 func AuthMiddleware(requiredUser, requiredPassword, realm string) endpoint.Middleware {
68         requiredUserBytes := toHashSlice([]byte(requiredUser))
69         requiredPasswordBytes := toHashSlice([]byte(requiredPassword))
70
71         return func(next endpoint.Endpoint) endpoint.Endpoint {
72                 return func(ctx context.Context, request interface{}) (interface{}, error) {
73                         auth, ok := ctx.Value(httptransport.ContextKeyRequestAuthorization).(string)
74                         if !ok {
75                                 return nil, AuthError{realm}
76                         }
77
78                         givenUser, givenPassword, ok := parseBasicAuth(auth)
79                         if !ok {
80                                 return nil, AuthError{realm}
81                         }
82
83                         givenUserBytes := toHashSlice(givenUser)
84                         givenPasswordBytes := toHashSlice(givenPassword)
85
86                         if subtle.ConstantTimeCompare(givenUserBytes, requiredUserBytes) == 0 ||
87                                 subtle.ConstantTimeCompare(givenPasswordBytes, requiredPasswordBytes) == 0 {
88                                 return nil, AuthError{realm}
89                         }
90
91                         return next(ctx, request)
92                 }
93         }
94 }