github.com/Tyktechnologies/tyk@v2.9.5+incompatible/gateway/mw_jwt.go (about)

     1  package gateway
     2  
     3  import (
     4  	"crypto/md5"
     5  	"crypto/x509"
     6  	"encoding/base64"
     7  	"encoding/json"
     8  	"encoding/pem"
     9  	"errors"
    10  	"fmt"
    11  	"net/http"
    12  	"strings"
    13  	"sync"
    14  	"time"
    15  
    16  	jwt "github.com/dgrijalva/jwt-go"
    17  	cache "github.com/pmylund/go-cache"
    18  
    19  	"github.com/TykTechnologies/tyk/apidef"
    20  	"github.com/TykTechnologies/tyk/user"
    21  )
    22  
    23  type JWTMiddleware struct {
    24  	BaseMiddleware
    25  }
    26  
    27  const (
    28  	KID       = "kid"
    29  	SUB       = "sub"
    30  	HMACSign  = "hmac"
    31  	RSASign   = "rsa"
    32  	ECDSASign = "ecdsa"
    33  )
    34  
    35  func (k *JWTMiddleware) Name() string {
    36  	return "JWTMiddleware"
    37  }
    38  
    39  func (k *JWTMiddleware) EnabledForSpec() bool {
    40  	return k.Spec.EnableJWT
    41  }
    42  
    43  var JWKCache *cache.Cache
    44  
    45  type JWK struct {
    46  	Alg string   `json:"alg"`
    47  	Kty string   `json:"kty"`
    48  	Use string   `json:"use"`
    49  	X5c []string `json:"x5c"`
    50  	N   string   `json:"n"`
    51  	E   string   `json:"e"`
    52  	KID string   `json:"kid"`
    53  	X5t string   `json:"x5t"`
    54  }
    55  
    56  type JWKs struct {
    57  	Keys []JWK `json:"keys"`
    58  }
    59  
    60  func (k *JWTMiddleware) getSecretFromURL(url, kid, keyType string) ([]byte, error) {
    61  	// Implement a cache
    62  	if JWKCache == nil {
    63  		k.Logger().Debug("Creating JWK Cache")
    64  		JWKCache = cache.New(240*time.Second, 30*time.Second)
    65  	}
    66  
    67  	var jwkSet JWKs
    68  	cachedJWK, found := JWKCache.Get(k.Spec.APIID)
    69  	if !found {
    70  		// Get the JWK
    71  		k.Logger().Debug("Pulling JWK")
    72  		resp, err := http.Get(url)
    73  		if err != nil {
    74  			k.Logger().WithError(err).Error("Failed to get resource URL")
    75  			return nil, err
    76  		}
    77  		defer resp.Body.Close()
    78  
    79  		// Decode it
    80  		if err := json.NewDecoder(resp.Body).Decode(&jwkSet); err != nil {
    81  			k.Logger().WithError(err).Error("Failed to decode body JWK")
    82  			return nil, err
    83  		}
    84  
    85  		// Cache it
    86  		k.Logger().Debug("Caching JWK")
    87  		JWKCache.Set(k.Spec.APIID, jwkSet, cache.DefaultExpiration)
    88  	} else {
    89  		jwkSet = cachedJWK.(JWKs)
    90  	}
    91  
    92  	k.Logger().Debug("Checking JWKs...")
    93  	for _, val := range jwkSet.Keys {
    94  		if val.KID != kid || strings.ToLower(val.Kty) != strings.ToLower(keyType) {
    95  			continue
    96  		}
    97  		if len(val.X5c) > 0 {
    98  			// Use the first cert only
    99  			decodedCert, err := base64.StdEncoding.DecodeString(val.X5c[0])
   100  			if err != nil {
   101  				return nil, err
   102  			}
   103  			k.Logger().Debug("Found cert! Replying...")
   104  			k.Logger().Debug("Cert was: ", string(decodedCert))
   105  			return decodedCert, nil
   106  		}
   107  		return nil, errors.New("no certificates in JWK")
   108  	}
   109  
   110  	return nil, errors.New("No matching KID could be found")
   111  }
   112  
   113  func (k *JWTMiddleware) getIdentityFromToken(token *jwt.Token) (string, error) {
   114  	// Check which claim is used for the id - kid or sub header
   115  	// If is not supposed to ignore KID - will use this as ID if not empty
   116  	if !k.Spec.APIDefinition.JWTSkipKid {
   117  		if tykId, idFound := token.Header[KID].(string); idFound {
   118  			k.Logger().Debug("Found: ", tykId)
   119  			return tykId, nil
   120  		}
   121  	}
   122  	// In case KID was empty or was set to ignore KID ==> Will try to get the Id from JWTIdentityBaseField or fallback to 'sub'
   123  	tykId, err := k.getUserIdFromClaim(token.Claims.(jwt.MapClaims))
   124  	return tykId, err
   125  }
   126  
   127  func (k *JWTMiddleware) getSecretToVerifySignature(r *http.Request, token *jwt.Token) ([]byte, error) {
   128  	config := k.Spec.APIDefinition
   129  	// Check for central JWT source
   130  	if config.JWTSource != "" {
   131  		// Is it a URL?
   132  		if httpScheme.MatchString(config.JWTSource) {
   133  			secret, err := k.getSecretFromURL(config.JWTSource, token.Header[KID].(string), k.Spec.JWTSigningMethod)
   134  			if err != nil {
   135  				return nil, err
   136  			}
   137  
   138  			return secret, nil
   139  		}
   140  
   141  		// If not, return the actual value
   142  		decodedCert, err := base64.StdEncoding.DecodeString(config.JWTSource)
   143  		if err != nil {
   144  			return nil, err
   145  		}
   146  
   147  		// Is decoded url too?
   148  		if httpScheme.MatchString(string(decodedCert)) {
   149  			secret, err := k.getSecretFromURL(string(decodedCert), token.Header[KID].(string), k.Spec.JWTSigningMethod)
   150  			if err != nil {
   151  				return nil, err
   152  			}
   153  
   154  			return secret, nil
   155  		}
   156  
   157  		return decodedCert, nil // Returns the decoded secret
   158  	}
   159  
   160  	// If we are here, there's no central JWT source
   161  
   162  	// Get the ID from the token (in KID header or configured claim or SUB claim)
   163  	tykId, err := k.getIdentityFromToken(token)
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  
   168  	// Couldn't base64 decode the kid, so lets try it raw
   169  	k.Logger().Debug("Getting key: ", tykId)
   170  	session, rawKeyExists := k.CheckSessionAndIdentityForValidKey(&tykId, r)
   171  	if !rawKeyExists {
   172  		return nil, errors.New("token invalid, key not found")
   173  	}
   174  	return []byte(session.JWTData.Secret), nil
   175  }
   176  
   177  func (k *JWTMiddleware) getPolicyIDFromToken(claims jwt.MapClaims) (string, bool) {
   178  	policyID, foundPolicy := claims[k.Spec.JWTPolicyFieldName].(string)
   179  	if !foundPolicy {
   180  		k.Logger().Error("Could not identify a policy to apply to this token from field")
   181  		return "", false
   182  	}
   183  
   184  	if policyID == "" {
   185  		k.Logger().Error("Policy field has empty value")
   186  		return "", false
   187  	}
   188  
   189  	return policyID, true
   190  }
   191  
   192  func (k *JWTMiddleware) getBasePolicyID(r *http.Request, claims jwt.MapClaims) (policyID string, found bool) {
   193  	if k.Spec.JWTPolicyFieldName != "" {
   194  		policyID, found = k.getPolicyIDFromToken(claims)
   195  		return
   196  	} else if k.Spec.JWTClientIDBaseField != "" {
   197  		clientID, clientIDFound := claims[k.Spec.JWTClientIDBaseField].(string)
   198  		if !clientIDFound {
   199  			k.Logger().Error("Could not identify a policy to apply to this token from field")
   200  			return
   201  		}
   202  
   203  		// Check for a regular token that matches this client ID
   204  		clientSession, exists := k.CheckSessionAndIdentityForValidKey(&clientID, r)
   205  		if !exists {
   206  			return
   207  		}
   208  
   209  		pols := clientSession.GetPolicyIDs()
   210  		if len(pols) < 1 {
   211  			return
   212  		}
   213  
   214  		// Use the policy from the client ID
   215  		return pols[0], true
   216  	}
   217  
   218  	return
   219  }
   220  
   221  func (k *JWTMiddleware) getUserIdFromClaim(claims jwt.MapClaims) (string, error) {
   222  	var userId string
   223  	var found = false
   224  
   225  	if k.Spec.JWTIdentityBaseField != "" {
   226  		if userId, found = claims[k.Spec.JWTIdentityBaseField].(string); found {
   227  			if len(userId) > 0 {
   228  				k.Logger().WithField("userId", userId).Debug("Found User Id in Base Field")
   229  				return userId, nil
   230  			}
   231  			message := "found an empty user ID in predefined base field claim " + k.Spec.JWTIdentityBaseField
   232  			k.Logger().Error(message)
   233  			return "", errors.New(message)
   234  		}
   235  
   236  		if !found {
   237  			k.Logger().WithField("Base Field", k.Spec.JWTIdentityBaseField).Warning("Base Field claim not found, trying to find user ID in 'sub' claim.")
   238  		}
   239  	}
   240  
   241  	if userId, found = claims[SUB].(string); found {
   242  		if len(userId) > 0 {
   243  			k.Logger().WithField("userId", userId).Debug("Found User Id in 'sub' claim")
   244  			return userId, nil
   245  		}
   246  		message := "found an empty user ID in sub claim"
   247  		k.Logger().Error(message)
   248  		return "", errors.New(message)
   249  	}
   250  
   251  	message := "no suitable claims for user ID were found"
   252  	k.Logger().Error(message)
   253  	return "", errors.New(message)
   254  }
   255  
   256  func getScopeFromClaim(claims jwt.MapClaims, scopeClaimName string) []string {
   257  	// get claim with scopes and turn it into slice of strings
   258  	if scope, found := claims[scopeClaimName].(string); found {
   259  		return strings.Split(scope, " ") // by standard is space separated list of values
   260  	}
   261  
   262  	// claim with scopes is optional so return nothing if it is not present
   263  	return nil
   264  }
   265  
   266  func mapScopeToPolicies(mapping map[string]string, scope []string) []string {
   267  	polIDs := []string{}
   268  
   269  	// add all policies matched from scope-policy mapping
   270  	policiesToApply := map[string]bool{}
   271  	for _, scopeItem := range scope {
   272  		if policyID, ok := mapping[scopeItem]; ok {
   273  			policiesToApply[policyID] = true
   274  		}
   275  	}
   276  	for id := range policiesToApply {
   277  		polIDs = append(polIDs, id)
   278  	}
   279  
   280  	return polIDs
   281  }
   282  
   283  // processCentralisedJWT Will check a JWT token centrally against the secret stored in the API Definition.
   284  func (k *JWTMiddleware) processCentralisedJWT(r *http.Request, token *jwt.Token) (error, int) {
   285  	k.Logger().Debug("JWT authority is centralised")
   286  
   287  	claims := token.Claims.(jwt.MapClaims)
   288  	baseFieldData, err := k.getUserIdFromClaim(claims)
   289  	if err != nil {
   290  		k.reportLoginFailure("[NOT FOUND]", r)
   291  		return err, http.StatusForbidden
   292  	}
   293  
   294  	// Generate a virtual token
   295  	data := []byte(baseFieldData)
   296  	keyID := fmt.Sprintf("%x", md5.Sum(data))
   297  	sessionID := generateToken(k.Spec.OrgID, keyID)
   298  	updateSession := false
   299  
   300  	k.Logger().Debug("JWT Temporary session ID is: ", sessionID)
   301  
   302  	session, exists := k.CheckSessionAndIdentityForValidKey(&sessionID, r)
   303  	isDefaultPol := false
   304  	basePolicyID := ""
   305  	foundPolicy := false
   306  	if !exists {
   307  		// Create it
   308  		k.Logger().Debug("Key does not exist, creating")
   309  
   310  		// We need a base policy as a template, either get it from the token itself OR a proxy client ID within Tyk
   311  		basePolicyID, foundPolicy = k.getBasePolicyID(r, claims)
   312  		if !foundPolicy {
   313  			if len(k.Spec.JWTDefaultPolicies) == 0 {
   314  				k.reportLoginFailure(baseFieldData, r)
   315  				return errors.New("key not authorized: no matching policy found"), http.StatusForbidden
   316  			} else {
   317  				isDefaultPol = true
   318  				basePolicyID = k.Spec.JWTDefaultPolicies[0]
   319  			}
   320  		}
   321  
   322  		session, err = generateSessionFromPolicy(basePolicyID,
   323  			k.Spec.OrgID,
   324  			true)
   325  
   326  		// If base policy is one of the defaults, apply other ones as well
   327  		if isDefaultPol {
   328  			for _, pol := range k.Spec.JWTDefaultPolicies {
   329  				if !contains(session.ApplyPolicies, pol) {
   330  					session.ApplyPolicies = append(session.ApplyPolicies, pol)
   331  				}
   332  			}
   333  		}
   334  
   335  		if err := k.ApplyPolicies(&session); err != nil {
   336  			return errors.New("failed to create key: " + err.Error()), http.StatusInternalServerError
   337  		}
   338  
   339  		if err != nil {
   340  			k.reportLoginFailure(baseFieldData, r)
   341  			k.Logger().Error("Could not find a valid policy to apply to this token!")
   342  			return errors.New("key not authorized: no matching policy"), http.StatusForbidden
   343  		}
   344  
   345  		//override session expiry with JWT if longer lived
   346  		if f, ok := claims["exp"].(float64); ok {
   347  			if int64(f)-session.Expires > 0 {
   348  				session.Expires = int64(f)
   349  			}
   350  		}
   351  
   352  		session.SetMetaData(map[string]interface{}{"TykJWTSessionID": sessionID})
   353  		session.Alias = baseFieldData
   354  
   355  		// Update the session in the session manager in case it gets called again
   356  		updateSession = true
   357  		k.Logger().Debug("Policy applied to key")
   358  	} else {
   359  		// extract policy ID from JWT token
   360  		basePolicyID, foundPolicy = k.getBasePolicyID(r, claims)
   361  		if !foundPolicy {
   362  			if len(k.Spec.JWTDefaultPolicies) == 0 {
   363  				k.reportLoginFailure(baseFieldData, r)
   364  				return errors.New("key not authorized: no matching policy found"), http.StatusForbidden
   365  			} else {
   366  				isDefaultPol = true
   367  				basePolicyID = k.Spec.JWTDefaultPolicies[0]
   368  			}
   369  		}
   370  		// check if we received a valid policy ID in claim
   371  		policiesMu.RLock()
   372  		policy, ok := policiesByID[basePolicyID]
   373  		policiesMu.RUnlock()
   374  		if !ok {
   375  			k.reportLoginFailure(baseFieldData, r)
   376  			k.Logger().Error("Policy ID found is invalid!")
   377  			return errors.New("key not authorized: no matching policy"), http.StatusForbidden
   378  		}
   379  		// check if token for this session was switched to another valid policy
   380  		pols := session.GetPolicyIDs()
   381  		if len(pols) == 0 {
   382  			k.reportLoginFailure(baseFieldData, r)
   383  			k.Logger().Error("No policies for the found session. Failing Request.")
   384  			return errors.New("key not authorized: no matching policy found"), http.StatusForbidden
   385  		}
   386  
   387  		defaultPolicyListChanged := false
   388  
   389  		if isDefaultPol {
   390  			// check a policy is removed/added from/to default policies
   391  
   392  			for _, pol := range session.GetPolicyIDs() {
   393  				if !contains(k.Spec.JWTDefaultPolicies, pol) && basePolicyID != pol {
   394  					defaultPolicyListChanged = true
   395  				}
   396  			}
   397  
   398  			for _, defPol := range k.Spec.JWTDefaultPolicies {
   399  				if !contains(session.GetPolicyIDs(), defPol) {
   400  					defaultPolicyListChanged = true
   401  				}
   402  			}
   403  		}
   404  
   405  		if !contains(pols, basePolicyID) || defaultPolicyListChanged {
   406  			if policy.OrgID != k.Spec.OrgID {
   407  				k.reportLoginFailure(baseFieldData, r)
   408  				k.Logger().Error("Policy ID found is invalid (wrong ownership)!")
   409  				return errors.New("key not authorized: no matching policy"), http.StatusForbidden
   410  			}
   411  			// apply new policy to session and update session
   412  			updateSession = true
   413  			session.SetPolicies(basePolicyID)
   414  
   415  			if isDefaultPol {
   416  				for _, pol := range k.Spec.JWTDefaultPolicies {
   417  					if !contains(session.ApplyPolicies, pol) {
   418  						session.ApplyPolicies = append(session.ApplyPolicies, pol)
   419  					}
   420  				}
   421  			}
   422  
   423  			if err := k.ApplyPolicies(&session); err != nil {
   424  				k.reportLoginFailure(baseFieldData, r)
   425  				k.Logger().WithError(err).Error("Could not apply new policy to session")
   426  				return errors.New("key not authorized: could not apply new policy"), http.StatusForbidden
   427  			}
   428  		}
   429  
   430  		//override session expiry with JWT if longer lived
   431  		if f, ok := claims["exp"].(float64); ok {
   432  			if int64(f)-session.Expires > 0 {
   433  				session.Expires = int64(f)
   434  				updateSession = true
   435  			}
   436  		}
   437  	}
   438  
   439  	// apply policies from scope if scope-to-policy mapping is specified for this API
   440  	if len(k.Spec.JWTScopeToPolicyMapping) != 0 {
   441  		scopeClaimName := k.Spec.JWTScopeClaimName
   442  		if scopeClaimName == "" {
   443  			scopeClaimName = "scope"
   444  		}
   445  
   446  		if scope := getScopeFromClaim(claims, scopeClaimName); scope != nil {
   447  			polIDs := []string{
   448  				basePolicyID, // add base policy as a first one
   449  			}
   450  
   451  			// // If specified, scopes should not use default policy
   452  			if isDefaultPol {
   453  				polIDs = []string{}
   454  			}
   455  
   456  			// add all policies matched from scope-policy mapping
   457  			mappedPolIDs := mapScopeToPolicies(k.Spec.JWTScopeToPolicyMapping, scope)
   458  
   459  			polIDs = append(polIDs, mappedPolIDs...)
   460  
   461  			// check if we need to update session
   462  			if !updateSession {
   463  				updateSession = !session.PoliciesEqualTo(polIDs)
   464  			}
   465  
   466  			session.SetPolicies(polIDs...)
   467  
   468  			// multiple policies assigned to a key, check if it is applicable
   469  			if err := k.ApplyPolicies(&session); err != nil {
   470  				k.reportLoginFailure(baseFieldData, r)
   471  				k.Logger().WithError(err).Error("Could not several policies from scope-claim mapping to JWT to session")
   472  				return errors.New("key not authorized: could not apply several policies"), http.StatusForbidden
   473  			}
   474  		}
   475  	}
   476  
   477  	k.Logger().Debug("Key found")
   478  	switch k.Spec.BaseIdentityProvidedBy {
   479  	case apidef.JWTClaim, apidef.UnsetAuth:
   480  		ctxSetSession(r, &session, sessionID, updateSession)
   481  
   482  		if updateSession {
   483  			SessionCache.Set(session.GetKeyHash(), session, cache.DefaultExpiration)
   484  		}
   485  	}
   486  	ctxSetJWTContextVars(k.Spec, r, token)
   487  
   488  	return nil, http.StatusOK
   489  }
   490  
   491  func (k *JWTMiddleware) reportLoginFailure(tykId string, r *http.Request) {
   492  	// Fire Authfailed Event
   493  	AuthFailed(k, r, tykId)
   494  
   495  	// Report in health check
   496  	reportHealthValue(k.Spec, KeyFailure, "1")
   497  }
   498  
   499  func (k *JWTMiddleware) processOneToOneTokenMap(r *http.Request, token *jwt.Token) (error, int) {
   500  	// Get the ID from the token
   501  	tykId, err := k.getIdentityFromToken(token)
   502  	if err != nil {
   503  		k.reportLoginFailure(tykId, r)
   504  		return err, http.StatusNotFound
   505  	}
   506  
   507  	k.Logger().Debug("Using raw key ID: ", tykId)
   508  	session, exists := k.CheckSessionAndIdentityForValidKey(&tykId, r)
   509  	if !exists {
   510  		k.reportLoginFailure(tykId, r)
   511  		return errors.New("Key not authorized"), http.StatusForbidden
   512  	}
   513  
   514  	k.Logger().Debug("Raw key ID found.")
   515  	ctxSetSession(r, &session, tykId, false)
   516  	ctxSetJWTContextVars(k.Spec, r, token)
   517  	return nil, http.StatusOK
   518  }
   519  
   520  // getAuthType overrides BaseMiddleware.getAuthType.
   521  func (k *JWTMiddleware) getAuthType() string {
   522  	return jwtType
   523  }
   524  
   525  func (k *JWTMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Request, _ interface{}) (error, int) {
   526  	if ctxGetRequestStatus(r) == StatusOkAndIgnore {
   527  		return nil, http.StatusOK
   528  	}
   529  
   530  	logger := k.Logger()
   531  	var tykId string
   532  
   533  	rawJWT, config := k.getAuthToken(k.getAuthType(), r)
   534  
   535  	if rawJWT == "" {
   536  		// No header value, fail
   537  		logger.Info("Attempted access with malformed header, no JWT auth header found.")
   538  
   539  		log.Debug("Looked in: ", config.AuthHeaderName)
   540  		log.Debug("Raw data was: ", rawJWT)
   541  		log.Debug("Headers are: ", r.Header)
   542  
   543  		k.reportLoginFailure(tykId, r)
   544  		return errors.New("Authorization field missing"), http.StatusBadRequest
   545  	}
   546  
   547  	// enable bearer token format
   548  	rawJWT = stripBearer(rawJWT)
   549  
   550  	// Use own validation logic, see below
   551  	parser := &jwt.Parser{SkipClaimsValidation: true}
   552  
   553  	// Verify the token
   554  	token, err := parser.Parse(rawJWT, func(token *jwt.Token) (interface{}, error) {
   555  		// Don't forget to validate the alg is what you expect:
   556  		switch k.Spec.JWTSigningMethod {
   557  		case HMACSign:
   558  			if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
   559  				return nil, fmt.Errorf("Unexpected signing method: %v and not HMAC signature", token.Header["alg"])
   560  			}
   561  		case RSASign:
   562  			if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
   563  				return nil, fmt.Errorf("Unexpected signing method: %v and not RSA signature", token.Header["alg"])
   564  			}
   565  		case ECDSASign:
   566  			if _, ok := token.Method.(*jwt.SigningMethodECDSA); !ok {
   567  				return nil, fmt.Errorf("Unexpected signing method: %v and not ECDSA signature", token.Header["alg"])
   568  			}
   569  		default:
   570  			logger.Warning("No signing method found in API Definition, defaulting to HMAC signature")
   571  			if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
   572  				return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
   573  			}
   574  		}
   575  
   576  		val, err := k.getSecretToVerifySignature(r, token)
   577  		if err != nil {
   578  			k.Logger().WithError(err).Error("Couldn't get token")
   579  			return nil, err
   580  		}
   581  		switch k.Spec.JWTSigningMethod {
   582  		case RSASign, ECDSASign:
   583  			key, err := ParseRSAPublicKey(val)
   584  			if err != nil {
   585  				logger.WithError(err).Error("Failed to decode JWT key")
   586  				return nil, err
   587  			}
   588  			return key, nil
   589  		default:
   590  			return val, nil
   591  		}
   592  	})
   593  
   594  	if err == nil && token.Valid {
   595  		if jwtErr := k.timeValidateJWTClaims(token.Claims.(jwt.MapClaims)); jwtErr != nil {
   596  			return errors.New("Key not authorized: " + jwtErr.Error()), http.StatusUnauthorized
   597  		}
   598  
   599  		// Token is valid - let's move on
   600  
   601  		// Are we mapping to a central JWT Secret?
   602  		if k.Spec.JWTSource != "" {
   603  			return k.processCentralisedJWT(r, token)
   604  		}
   605  
   606  		// No, let's try one-to-one mapping
   607  		return k.processOneToOneTokenMap(r, token)
   608  	}
   609  
   610  	logger.Info("Attempted JWT access with non-existent key.")
   611  	k.reportLoginFailure(tykId, r)
   612  	if err != nil {
   613  		logger.WithError(err).Error("JWT validation error")
   614  		return errors.New("Key not authorized:" + err.Error()), http.StatusForbidden
   615  	}
   616  	return errors.New("Key not authorized"), http.StatusForbidden
   617  }
   618  
   619  func ParseRSAPublicKey(data []byte) (interface{}, error) {
   620  	input := data
   621  	block, _ := pem.Decode(data)
   622  	if block != nil {
   623  		input = block.Bytes
   624  	}
   625  	var pub interface{}
   626  	var err error
   627  	pub, err = x509.ParsePKIXPublicKey(input)
   628  	if err != nil {
   629  		cert, err0 := x509.ParseCertificate(input)
   630  		if err0 != nil {
   631  			return nil, err0
   632  		}
   633  		pub = cert.PublicKey
   634  		err = nil
   635  	}
   636  	return pub, err
   637  }
   638  
   639  func (k *JWTMiddleware) timeValidateJWTClaims(c jwt.MapClaims) *jwt.ValidationError {
   640  	vErr := new(jwt.ValidationError)
   641  	now := time.Now().Unix()
   642  	// The claims below are optional, by default, so if they are set to the
   643  	// default value in Go, let's not fail the verification for them.
   644  	if !c.VerifyExpiresAt(now-int64(k.Spec.JWTExpiresAtValidationSkew), false) {
   645  		vErr.Inner = errors.New("token has expired")
   646  		vErr.Errors |= jwt.ValidationErrorExpired
   647  	}
   648  
   649  	if c.VerifyIssuedAt(now+int64(k.Spec.JWTIssuedAtValidationSkew), false) == false {
   650  		vErr.Inner = errors.New("token used before issued")
   651  		vErr.Errors |= jwt.ValidationErrorIssuedAt
   652  	}
   653  
   654  	if c.VerifyNotBefore(now+int64(k.Spec.JWTNotBeforeValidationSkew), false) == false {
   655  		vErr.Inner = errors.New("token is not valid yet")
   656  		vErr.Errors |= jwt.ValidationErrorNotValidYet
   657  	}
   658  
   659  	if vErr.Errors == 0 {
   660  		return nil
   661  	}
   662  
   663  	return vErr
   664  }
   665  
   666  func ctxSetJWTContextVars(s *APISpec, r *http.Request, token *jwt.Token) {
   667  	// Flatten claims and add to context
   668  	if !s.EnableContextVars {
   669  		return
   670  	}
   671  	if cnt := ctxGetData(r); cnt != nil {
   672  		claimPrefix := "jwt_claims_"
   673  
   674  		for claimName, claimValue := range token.Header {
   675  			claim := claimPrefix + claimName
   676  			cnt[claim] = claimValue
   677  		}
   678  
   679  		for claimName, claimValue := range token.Claims.(jwt.MapClaims) {
   680  			claim := claimPrefix + claimName
   681  			cnt[claim] = claimValue
   682  		}
   683  
   684  		// Key data
   685  		cnt["token"] = ctxGetAuthToken(r)
   686  
   687  		ctxSetData(r, cnt)
   688  	}
   689  }
   690  
   691  func generateSessionFromPolicy(policyID, orgID string, enforceOrg bool) (user.SessionState, error) {
   692  	policiesMu.RLock()
   693  	policy, ok := policiesByID[policyID]
   694  	policiesMu.RUnlock()
   695  	session := user.SessionState{Mutex: &sync.RWMutex{}}
   696  	if !ok {
   697  		return session, errors.New("Policy not found")
   698  	}
   699  	// Check ownership, policy org owner must be the same as API,
   700  	// otherwise youcould overwrite a session key with a policy from a different org!
   701  
   702  	if enforceOrg {
   703  		if policy.OrgID != orgID {
   704  			log.Error("Attempting to apply policy from different organisation to key, skipping")
   705  			return session, errors.New("Key not authorized: no matching policy")
   706  		}
   707  	} else {
   708  		// Org isn;t enforced, so lets use the policy baseline
   709  		orgID = policy.OrgID
   710  	}
   711  
   712  	session.SetPolicies(policyID)
   713  	session.OrgID = orgID
   714  	session.Allowance = policy.Rate // This is a legacy thing, merely to make sure output is consistent. Needs to be purged
   715  	session.Rate = policy.Rate
   716  	session.Per = policy.Per
   717  	session.ThrottleInterval = policy.ThrottleInterval
   718  	session.ThrottleRetryLimit = policy.ThrottleRetryLimit
   719  	session.QuotaMax = policy.QuotaMax
   720  	session.QuotaRenewalRate = policy.QuotaRenewalRate
   721  	session.AccessRights = make(map[string]user.AccessDefinition)
   722  	for apiID, access := range policy.AccessRights {
   723  		session.AccessRights[apiID] = access
   724  	}
   725  	session.HMACEnabled = policy.HMACEnabled
   726  	session.EnableHTTPSignatureValidation = policy.EnableHTTPSignatureValidation
   727  	session.IsInactive = policy.IsInactive
   728  	session.Tags = policy.Tags
   729  
   730  	if policy.KeyExpiresIn > 0 {
   731  		session.Expires = time.Now().Unix() + policy.KeyExpiresIn
   732  	}
   733  
   734  	return session, nil
   735  }