-
Notifications
You must be signed in to change notification settings - Fork 6
/
auth.go
97 lines (83 loc) · 2.44 KB
/
auth.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package reggie
import (
"encoding/json"
"errors"
"fmt"
"regexp"
"strings"
"github.com/mitchellh/mapstructure"
)
var (
authHeaderMatcher = regexp.MustCompile("(?i).*(bearer|basic).*")
)
type (
authHeader struct {
Realm string
Service string
Scope string
}
authInfo struct {
Token string `json:"token"`
AccessToken string `json:"access_token"`
}
)
func (client *Client) retryRequestWithAuth(originalRequest *Request, originalResponse *Response) (*Response, error) {
authHeaderRaw := originalResponse.Header().Get("Www-Authenticate")
if authHeaderRaw == "" {
return originalResponse, nil
}
for k, _ := range originalRequest.QueryParam {
originalRequest.QueryParam.Del(k)
}
if originalRequest.retryCallback != nil {
err := originalRequest.retryCallback(originalRequest)
if err != nil {
return nil, fmt.Errorf("retry callback returned error: %s", err)
}
}
authenticationType := authHeaderMatcher.ReplaceAllString(authHeaderRaw, "$1")
if strings.EqualFold(authenticationType, "bearer") {
h := parseAuthHeader(authHeaderRaw)
req := client.Client.NewRequest().
SetQueryParam("service", h.Service).
SetHeader("Accept", "application/json").
SetHeader("User-Agent", client.Config.UserAgent).
SetBasicAuth(client.Config.Username, client.Config.Password)
if s := client.Config.AuthScope; s != "" {
req.SetQueryParam("scope", s)
} else if h.Scope != "" {
req.SetQueryParam("scope", h.Scope)
}
authResp, err := req.Execute(GET, h.Realm)
if err != nil {
return nil, err
}
var info authInfo
bodyBytes := authResp.Body()
err = json.Unmarshal(bodyBytes, &info)
if err != nil {
return nil, err
}
token := info.Token
if token == "" {
token = info.AccessToken
}
originalRequest.SetAuthToken(token)
return originalRequest.Execute(originalRequest.Method, originalRequest.URL)
} else if strings.EqualFold(authenticationType, "basic") {
originalRequest.SetBasicAuth(client.Config.Username, client.Config.Password)
return originalRequest.Execute(originalRequest.Method, originalRequest.URL)
}
return nil, errors.New("something went wrong with authorization")
}
func parseAuthHeader(authHeaderRaw string) *authHeader {
re := regexp.MustCompile(`([a-zA-z]+)="(.+?)"`)
matches := re.FindAllStringSubmatch(authHeaderRaw, -1)
m := make(map[string]string)
for i := 0; i < len(matches); i++ {
m[matches[i][1]] = matches[i][2]
}
var h authHeader
mapstructure.Decode(m, &h)
return &h
}