1
17
18 package jwt
19
20 import (
21 "bytes"
22 "reflect"
23
24 "gopkg.in/go-jose/go-jose.v2/json"
25
26 "gopkg.in/go-jose/go-jose.v2"
27 )
28
29
30
31 type Builder interface {
32
33
34
35
36 Claims(i interface{}) Builder
37
38 Token() (*JSONWebToken, error)
39
40 FullSerialize() (string, error)
41
42 CompactSerialize() (string, error)
43 }
44
45
46
47
48 type NestedBuilder interface {
49
50
51
52
53 Claims(i interface{}) NestedBuilder
54
55 Token() (*NestedJSONWebToken, error)
56
57 FullSerialize() (string, error)
58
59 CompactSerialize() (string, error)
60 }
61
62 type builder struct {
63 payload map[string]interface{}
64 err error
65 }
66
67 type signedBuilder struct {
68 builder
69 sig jose.Signer
70 }
71
72 type encryptedBuilder struct {
73 builder
74 enc jose.Encrypter
75 }
76
77 type nestedBuilder struct {
78 builder
79 sig jose.Signer
80 enc jose.Encrypter
81 }
82
83
84 func Signed(sig jose.Signer) Builder {
85 return &signedBuilder{
86 sig: sig,
87 }
88 }
89
90
91 func Encrypted(enc jose.Encrypter) Builder {
92 return &encryptedBuilder{
93 enc: enc,
94 }
95 }
96
97
98
99 func SignedAndEncrypted(sig jose.Signer, enc jose.Encrypter) NestedBuilder {
100 if contentType, _ := enc.Options().ExtraHeaders[jose.HeaderContentType].(jose.ContentType); contentType != "JWT" {
101 return &nestedBuilder{
102 builder: builder{
103 err: ErrInvalidContentType,
104 },
105 }
106 }
107 return &nestedBuilder{
108 sig: sig,
109 enc: enc,
110 }
111 }
112
113 func (b builder) claims(i interface{}) builder {
114 if b.err != nil {
115 return b
116 }
117
118 m, ok := i.(map[string]interface{})
119 switch {
120 case ok:
121 return b.merge(m)
122 case reflect.Indirect(reflect.ValueOf(i)).Kind() == reflect.Struct:
123 m, err := normalize(i)
124 if err != nil {
125 return builder{
126 err: err,
127 }
128 }
129 return b.merge(m)
130 default:
131 return builder{
132 err: ErrInvalidClaims,
133 }
134 }
135 }
136
137 func normalize(i interface{}) (map[string]interface{}, error) {
138 m := make(map[string]interface{})
139
140 raw, err := json.Marshal(i)
141 if err != nil {
142 return nil, err
143 }
144
145 d := json.NewDecoder(bytes.NewReader(raw))
146 d.SetNumberType(json.UnmarshalJSONNumber)
147
148 if err := d.Decode(&m); err != nil {
149 return nil, err
150 }
151
152 return m, nil
153 }
154
155 func (b *builder) merge(m map[string]interface{}) builder {
156 p := make(map[string]interface{})
157 for k, v := range b.payload {
158 p[k] = v
159 }
160 for k, v := range m {
161 p[k] = v
162 }
163
164 return builder{
165 payload: p,
166 }
167 }
168
169 func (b *builder) token(p func(interface{}) ([]byte, error), h []jose.Header) (*JSONWebToken, error) {
170 return &JSONWebToken{
171 payload: p,
172 Headers: h,
173 }, nil
174 }
175
176 func (b *signedBuilder) Claims(i interface{}) Builder {
177 return &signedBuilder{
178 builder: b.builder.claims(i),
179 sig: b.sig,
180 }
181 }
182
183 func (b *signedBuilder) Token() (*JSONWebToken, error) {
184 sig, err := b.sign()
185 if err != nil {
186 return nil, err
187 }
188
189 h := make([]jose.Header, len(sig.Signatures))
190 for i, v := range sig.Signatures {
191 h[i] = v.Header
192 }
193
194 return b.builder.token(sig.Verify, h)
195 }
196
197 func (b *signedBuilder) CompactSerialize() (string, error) {
198 sig, err := b.sign()
199 if err != nil {
200 return "", err
201 }
202
203 return sig.CompactSerialize()
204 }
205
206 func (b *signedBuilder) FullSerialize() (string, error) {
207 sig, err := b.sign()
208 if err != nil {
209 return "", err
210 }
211
212 return sig.FullSerialize(), nil
213 }
214
215 func (b *signedBuilder) sign() (*jose.JSONWebSignature, error) {
216 if b.err != nil {
217 return nil, b.err
218 }
219
220 p, err := json.Marshal(b.payload)
221 if err != nil {
222 return nil, err
223 }
224
225 return b.sig.Sign(p)
226 }
227
228 func (b *encryptedBuilder) Claims(i interface{}) Builder {
229 return &encryptedBuilder{
230 builder: b.builder.claims(i),
231 enc: b.enc,
232 }
233 }
234
235 func (b *encryptedBuilder) CompactSerialize() (string, error) {
236 enc, err := b.encrypt()
237 if err != nil {
238 return "", err
239 }
240
241 return enc.CompactSerialize()
242 }
243
244 func (b *encryptedBuilder) FullSerialize() (string, error) {
245 enc, err := b.encrypt()
246 if err != nil {
247 return "", err
248 }
249
250 return enc.FullSerialize(), nil
251 }
252
253 func (b *encryptedBuilder) Token() (*JSONWebToken, error) {
254 enc, err := b.encrypt()
255 if err != nil {
256 return nil, err
257 }
258
259 return b.builder.token(enc.Decrypt, []jose.Header{enc.Header})
260 }
261
262 func (b *encryptedBuilder) encrypt() (*jose.JSONWebEncryption, error) {
263 if b.err != nil {
264 return nil, b.err
265 }
266
267 p, err := json.Marshal(b.payload)
268 if err != nil {
269 return nil, err
270 }
271
272 return b.enc.Encrypt(p)
273 }
274
275 func (b *nestedBuilder) Claims(i interface{}) NestedBuilder {
276 return &nestedBuilder{
277 builder: b.builder.claims(i),
278 sig: b.sig,
279 enc: b.enc,
280 }
281 }
282
283 func (b *nestedBuilder) Token() (*NestedJSONWebToken, error) {
284 enc, err := b.signAndEncrypt()
285 if err != nil {
286 return nil, err
287 }
288
289 return &NestedJSONWebToken{
290 enc: enc,
291 Headers: []jose.Header{enc.Header},
292 }, nil
293 }
294
295 func (b *nestedBuilder) CompactSerialize() (string, error) {
296 enc, err := b.signAndEncrypt()
297 if err != nil {
298 return "", err
299 }
300
301 return enc.CompactSerialize()
302 }
303
304 func (b *nestedBuilder) FullSerialize() (string, error) {
305 enc, err := b.signAndEncrypt()
306 if err != nil {
307 return "", err
308 }
309
310 return enc.FullSerialize(), nil
311 }
312
313 func (b *nestedBuilder) signAndEncrypt() (*jose.JSONWebEncryption, error) {
314 if b.err != nil {
315 return nil, b.err
316 }
317
318 p, err := json.Marshal(b.payload)
319 if err != nil {
320 return nil, err
321 }
322
323 sig, err := b.sig.Sign(p)
324 if err != nil {
325 return nil, err
326 }
327
328 p2, err := sig.CompactSerialize()
329 if err != nil {
330 return nil, err
331 }
332
333 return b.enc.Encrypt([]byte(p2))
334 }
335
View as plain text