github.com/brycereitano/goa@v0.0.0-20170315073847-8ffa6c85e265/middleware/security/jwt/resolver.go (about) 1 package jwt 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/rsa" 6 "net/http" 7 "sync" 8 ) 9 10 type ( 11 // Key represents a public key used to validate the incoming token signatures. 12 // The value must be of type *rsa.PublicKey, *ecdsa.PublicKey, []byte or string. 13 // Keys of type []byte or string are interpreted depending on the incoming request JWT token 14 // method (HMAC, RSA, etc.). 15 Key interface{} 16 17 // KeyResolver allows the management of keys used by the middleware to verify the signature of 18 // incoming requests. Keys are grouped by name allowing the authorization algorithm to select a 19 // group depending on the incoming request state (e.g. a header). The use of groups enables key 20 // rotation. 21 KeyResolver interface { 22 // SelectKeys returns the group of keys to be used for the incoming request. 23 SelectKeys(req *http.Request) []Key 24 } 25 26 // GroupResolver is a key resolver that switches on the value of a specified request header 27 // for selecting the key group used to authorize the incoming request. 28 GroupResolver struct { 29 *sync.RWMutex 30 keyHeader string 31 keyMap map[string][]Key 32 } 33 34 // simpleResolver uses a single immutable key group. 35 simpleResolver []Key 36 ) 37 38 // NewResolver returns a GroupResolver that uses the value of the request header with the given name 39 // to select the key group used for authorization. keys contains the initial set of key groups 40 // indexed by name. 41 func NewResolver(keys map[string][]Key, header string) (*GroupResolver, error) { 42 if header == "" { 43 return nil, ErrEmptyHeaderName 44 } 45 keyMap := make(map[string][]Key) 46 for name := range keys { 47 for _, keys := range keys[name] { 48 switch keys := keys.(type) { 49 case *rsa.PublicKey, *ecdsa.PublicKey, string, []byte: 50 keyMap[name] = append(keyMap[name], keys) 51 case []*rsa.PublicKey: 52 for _, key := range keys { 53 keyMap[name] = append(keyMap[name], key) 54 } 55 case []*ecdsa.PublicKey: 56 for _, key := range keys { 57 keyMap[name] = append(keyMap[name], key) 58 } 59 case [][]byte: 60 for _, key := range keys { 61 keyMap[name] = append(keyMap[name], key) 62 } 63 case []string: 64 for _, key := range keys { 65 keyMap[name] = append(keyMap[name], key) 66 } 67 default: 68 return nil, ErrInvalidKey 69 } 70 } 71 } 72 return &GroupResolver{ 73 RWMutex: &sync.RWMutex{}, 74 keyMap: keyMap, 75 keyHeader: header, 76 }, nil 77 } 78 79 // NewSimpleResolver returns a simple resolver. 80 func NewSimpleResolver(keys []Key) KeyResolver { 81 return simpleResolver(keys) 82 } 83 84 // AddKeys can be used to add keys to the resolver which will be referenced 85 // by the provided name. Acceptable types for keys include string, []string, 86 // *rsa.PublicKey or []*rsa.PublicKey. Multiple keys are allowed for a single 87 // key name to allow for key rotation. 88 func (kr *GroupResolver) AddKeys(name string, keys Key) error { 89 kr.Lock() 90 defer kr.Unlock() 91 switch keys := keys.(type) { 92 case *rsa.PublicKey, *ecdsa.PublicKey, []byte, string: 93 kr.keyMap[name] = append(kr.keyMap[name], keys) 94 case []*rsa.PublicKey: 95 for _, key := range keys { 96 kr.keyMap[name] = append(kr.keyMap[name], key) 97 } 98 case []*ecdsa.PublicKey: 99 for _, key := range keys { 100 kr.keyMap[name] = append(kr.keyMap[name], key) 101 } 102 case [][]byte: 103 for _, key := range keys { 104 kr.keyMap[name] = append(kr.keyMap[name], key) 105 } 106 case []string: 107 for _, key := range keys { 108 kr.keyMap[name] = append(kr.keyMap[name], key) 109 } 110 default: 111 return ErrInvalidKey 112 } 113 return nil 114 } 115 116 // RemoveAllKeys removes all keys from the resolver. 117 func (kr *GroupResolver) RemoveAllKeys() { 118 kr.Lock() 119 defer kr.Unlock() 120 kr.keyMap = make(map[string][]Key) 121 return 122 } 123 124 // RemoveKeys removes all keys from the resolver stored under the provided name. 125 func (kr *GroupResolver) RemoveKeys(name string) { 126 kr.Lock() 127 defer kr.Unlock() 128 delete(kr.keyMap, name) 129 return 130 } 131 132 // RemoveKey removes only the provided key stored under the provided name from 133 // the resolver. 134 func (kr *GroupResolver) RemoveKey(name string, key Key) { 135 kr.Lock() 136 defer kr.Unlock() 137 if keys, ok := kr.keyMap[name]; ok { 138 for i, keyItem := range keys { 139 if keyItem == key { 140 kr.keyMap[name] = append(keys[:i], keys[i+1:]...) 141 } 142 } 143 } 144 return 145 } 146 147 // GetAllKeys returns a list of all the keys stored in the resolver. 148 func (kr *GroupResolver) GetAllKeys() []Key { 149 kr.RLock() 150 defer kr.RUnlock() 151 var keys []Key 152 for name := range kr.keyMap { 153 for _, key := range kr.keyMap[name] { 154 keys = append(keys, key) 155 } 156 } 157 return keys 158 } 159 160 // GetKeys returns a list of all the keys stored in the resolver under the 161 // provided name. 162 func (kr *GroupResolver) GetKeys(name string) ([]Key, error) { 163 kr.RLock() 164 defer kr.RUnlock() 165 if keys, ok := kr.keyMap[name]; ok { 166 return keys, nil 167 } 168 return nil, ErrKeyDoesNotExist 169 } 170 171 // SelectKeys returns the keys in the group with the name identified by the request key selection 172 // header. If the header does value does not match a specific group then all keys are returned. 173 func (kr *GroupResolver) SelectKeys(req *http.Request) []Key { 174 keyName := req.Header.Get(kr.keyHeader) 175 kr.RLock() 176 defer kr.RUnlock() 177 if keyName != "" { 178 return kr.keyMap[keyName] 179 } 180 var keys []Key 181 for _, ks := range kr.keyMap { 182 keys = append(keys, ks...) 183 } 184 return keys 185 } 186 187 // SelectKeys returns the keys used to create the simple resolver. 188 func (sr simpleResolver) SelectKeys(req *http.Request) []Key { 189 return []Key(sr) 190 }