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  }