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 }