1 package jwt
2
3 import (
4 "net/http"
5 "net/url"
6 "strconv"
7 "strings"
8
9 "github.com/lestrrat-go/jwx/internal/pool"
10 "github.com/pkg/errors"
11 )
12
13
14
15
16
17 func ParseHeader(hdr http.Header, name string, options ...ParseOption) (Token, error) {
18 key := http.CanonicalHeaderKey(name)
19 v := strings.TrimSpace(hdr.Get(key))
20 if v == "" {
21 return nil, errors.Errorf(`empty header (%s)`, key)
22 }
23
24 if key == "Authorization" {
25
26
27 v = strings.TrimSpace(strings.TrimPrefix(v, "Bearer"))
28 }
29
30 return ParseString(v, options...)
31 }
32
33
34 func ParseForm(values url.Values, name string, options ...ParseOption) (Token, error) {
35 v := strings.TrimSpace(values.Get(name))
36 if v == "" {
37 return nil, errors.Errorf(`empty value (%s)`, name)
38 }
39
40 return ParseString(v, options...)
41 }
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 func ParseRequest(req *http.Request, options ...ParseOption) (Token, error) {
62 var hdrkeys []string
63 var formkeys []string
64 var parseOptions []ParseOption
65 for _, option := range options {
66
67 switch option.Ident() {
68 case identHeaderKey{}:
69 hdrkeys = append(hdrkeys, option.Value().(string))
70 case identFormKey{}:
71 formkeys = append(formkeys, option.Value().(string))
72 default:
73 parseOptions = append(parseOptions, option)
74 }
75 }
76 if len(hdrkeys) == 0 {
77 hdrkeys = append(hdrkeys, "Authorization")
78 }
79
80 mhdrs := pool.GetKeyToErrorMap()
81 defer pool.ReleaseKeyToErrorMap(mhdrs)
82 mfrms := pool.GetKeyToErrorMap()
83 defer pool.ReleaseKeyToErrorMap(mfrms)
84
85 for _, hdrkey := range hdrkeys {
86
87 if _, ok := req.Header[http.CanonicalHeaderKey(hdrkey)]; !ok {
88
89 continue
90 }
91
92 tok, err := ParseHeader(req.Header, hdrkey, parseOptions...)
93 if err != nil {
94 mhdrs[hdrkey] = err
95 continue
96 }
97 return tok, nil
98 }
99
100 if cl := req.ContentLength; cl > 0 {
101 if err := req.ParseForm(); err != nil {
102 return nil, errors.Wrap(err, `failed to parse form`)
103 }
104 }
105
106 for _, formkey := range formkeys {
107
108 if _, ok := req.Form[formkey]; !ok {
109
110 continue
111 }
112
113 tok, err := ParseForm(req.Form, formkey, parseOptions...)
114 if err != nil {
115 mfrms[formkey] = err
116 continue
117 }
118 return tok, nil
119 }
120
121
122 var triedHdrs strings.Builder
123 for i, hdrkey := range hdrkeys {
124 if i > 0 {
125 triedHdrs.WriteString(", ")
126 }
127 triedHdrs.WriteString(strconv.Quote(hdrkey))
128 }
129
130 var triedForms strings.Builder
131 for i, formkey := range formkeys {
132 if i > 0 {
133 triedForms.WriteString(", ")
134 }
135 triedForms.WriteString(strconv.Quote(formkey))
136 }
137
138 var b strings.Builder
139 b.WriteString(`failed to find a valid token in any location of the request (tried: [header keys: `)
140 b.WriteString(triedHdrs.String())
141 b.WriteByte(']')
142 if triedForms.Len() > 0 {
143 b.WriteString(", form keys: [")
144 b.WriteString(triedForms.String())
145 b.WriteByte(']')
146 }
147 b.WriteByte(')')
148
149 lmhdrs := len(mhdrs)
150 lmfrms := len(mfrms)
151 if lmhdrs > 0 || lmfrms > 0 {
152 b.WriteString(". Additionally, errors were encountered during attempts to parse")
153
154 if lmhdrs > 0 {
155 b.WriteString(" headers: (")
156 count := 0
157 for hdrkey, err := range mhdrs {
158 if count > 0 {
159 b.WriteString(", ")
160 }
161 b.WriteString("[header key: ")
162 b.WriteString(strconv.Quote(hdrkey))
163 b.WriteString(", error: ")
164 b.WriteString(strconv.Quote(err.Error()))
165 b.WriteString("]")
166 count++
167 }
168 b.WriteString(")")
169 }
170
171 if lmfrms > 0 {
172 count := 0
173 b.WriteString(" forms: (")
174 for formkey, err := range mfrms {
175 if count > 0 {
176 b.WriteString(", ")
177 }
178 b.WriteString("[form key: ")
179 b.WriteString(strconv.Quote(formkey))
180 b.WriteString(", error: ")
181 b.WriteString(strconv.Quote(err.Error()))
182 b.WriteString("]")
183 count++
184 }
185 }
186 }
187 return nil, errors.New(b.String())
188 }
189
View as plain text