...
1 package keyfunc
2
3 import (
4 "errors"
5 "fmt"
6
7 "github.com/golang-jwt/jwt/v5"
8 )
9
10
11 var ErrMultipleJWKSSize = errors.New("multiple JWKS must have one or more remote JWK Set resources")
12
13
14 type MultipleJWKS struct {
15 keySelector func(multiJWKS *MultipleJWKS, token *jwt.Token) (key interface{}, err error)
16 sets map[string]*JWKS
17 }
18
19
20
21
22
23
24 func GetMultiple(multiple map[string]Options, options MultipleOptions) (multiJWKS *MultipleJWKS, err error) {
25 if len(multiple) < 1 {
26 return nil, fmt.Errorf("multiple JWKS must have one or more remote JWK Set resources: %w", ErrMultipleJWKSSize)
27 }
28
29 if options.KeySelector == nil {
30 options.KeySelector = KeySelectorFirst
31 }
32
33 multiJWKS = &MultipleJWKS{
34 sets: make(map[string]*JWKS, len(multiple)),
35 keySelector: options.KeySelector,
36 }
37
38 for u, opts := range multiple {
39 jwks, err := Get(u, opts)
40 if err != nil {
41 return nil, fmt.Errorf("failed to get JWKS from %q: %w", u, err)
42 }
43 multiJWKS.sets[u] = jwks
44 }
45
46 return multiJWKS, nil
47 }
48
49
50
51 func (m *MultipleJWKS) JWKSets() map[string]*JWKS {
52 sets := make(map[string]*JWKS, len(m.sets))
53 for u, jwks := range m.sets {
54 sets[u] = jwks
55 }
56 return sets
57 }
58
59
60 func KeySelectorFirst(multiJWKS *MultipleJWKS, token *jwt.Token) (key interface{}, err error) {
61 kid, alg, err := kidAlg(token)
62 if err != nil {
63 return nil, err
64 }
65 for _, jwks := range multiJWKS.sets {
66 key, err = jwks.getKey(alg, kid)
67 if err == nil {
68 return key, nil
69 }
70 }
71 return nil, fmt.Errorf("failed to find key ID in multiple JWKS: %w", ErrKIDNotFound)
72 }
73
View as plain text