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

     1  package gateway
     2  
     3  import (
     4  	"net/http"
     5  	"strings"
     6  	"time"
     7  
     8  	"github.com/TykTechnologies/tyk/config"
     9  
    10  	"github.com/TykTechnologies/tyk/apidef"
    11  )
    12  
    13  const (
    14  	checkOAuthClientDeletedInetrval = 1 * time.Second
    15  )
    16  
    17  const (
    18  	ErrOAuthAuthorizationFieldMissing   = "oauth.auth_field_missing"
    19  	ErrOAuthAuthorizationFieldMalformed = "oauth.auth_field_malformed"
    20  	ErrOAuthKeyNotFound                 = "oauth.key_not_found"
    21  	ErrOAuthClientDeleted               = "oauth.client_deleted"
    22  )
    23  
    24  func init() {
    25  	TykErrors[ErrOAuthAuthorizationFieldMissing] = config.TykError{
    26  		Message: "Authorization field missing",
    27  		Code:    http.StatusBadRequest,
    28  	}
    29  
    30  	TykErrors[ErrOAuthAuthorizationFieldMalformed] = config.TykError{
    31  		Message: "Bearer token malformed",
    32  		Code:    http.StatusBadRequest,
    33  	}
    34  
    35  	TykErrors[ErrOAuthKeyNotFound] = config.TykError{
    36  		Message: "Key not authorised",
    37  		Code:    http.StatusForbidden,
    38  	}
    39  
    40  	TykErrors[ErrOAuthClientDeleted] = config.TykError{
    41  		Message: "Key not authorised. OAuth client access was revoked",
    42  		Code:    http.StatusForbidden,
    43  	}
    44  }
    45  
    46  // Oauth2KeyExists will check if the key being used to access the API is in the request data,
    47  // and then if the key is in the storage engine
    48  type Oauth2KeyExists struct {
    49  	BaseMiddleware
    50  }
    51  
    52  func (k *Oauth2KeyExists) Name() string {
    53  	return "Oauth2KeyExists"
    54  }
    55  
    56  func (k *Oauth2KeyExists) EnabledForSpec() bool {
    57  	return k.Spec.UseOauth2
    58  }
    59  
    60  // getAuthType overrides BaseMiddleware.getAuthType.
    61  func (k *Oauth2KeyExists) getAuthType() string {
    62  	return oauthType
    63  }
    64  
    65  // ProcessRequest will run any checks on the request on the way through the system, return an error to have the chain fail
    66  func (k *Oauth2KeyExists) ProcessRequest(w http.ResponseWriter, r *http.Request, _ interface{}) (error, int) {
    67  	if ctxGetRequestStatus(r) == StatusOkAndIgnore {
    68  		return nil, http.StatusOK
    69  	}
    70  
    71  	logger := k.Logger()
    72  	// We're using OAuth, start checking for access keys
    73  	token, _ := k.getAuthToken(k.getAuthType(), r)
    74  	parts := strings.Split(token, " ")
    75  
    76  	if len(parts) < 2 {
    77  		logger.Info("Attempted access with malformed header, no auth header found.")
    78  
    79  		return errorAndStatusCode(ErrOAuthAuthorizationFieldMissing)
    80  	}
    81  
    82  	if strings.ToLower(parts[0]) != "bearer" {
    83  		logger.Info("Bearer token malformed")
    84  
    85  		return errorAndStatusCode(ErrOAuthAuthorizationFieldMalformed)
    86  	}
    87  
    88  	accessToken := parts[1]
    89  	logger = logger.WithField("key", obfuscateKey(accessToken))
    90  
    91  	// get session for the given oauth token
    92  	session, keyExists := k.CheckSessionAndIdentityForValidKey(&accessToken, r)
    93  	if !keyExists {
    94  		logger.Warning("Attempted access with non-existent key.")
    95  
    96  		// Fire Authfailed Event
    97  		AuthFailed(k, r, accessToken)
    98  		// Report in health check
    99  		reportHealthValue(k.Spec, KeyFailure, "-1")
   100  
   101  		return errorAndStatusCode(ErrOAuthKeyNotFound)
   102  	}
   103  
   104  	// Make sure OAuth-client is still present
   105  	oauthClientDeletedKey := "oauth-del-" + k.Spec.APIID + session.OauthClientID
   106  	oauthClientDeleted := false
   107  	// check if that oauth client was deleted with using  memory cache first
   108  	if val, found := UtilCache.Get(oauthClientDeletedKey); found {
   109  		oauthClientDeleted = val.(bool)
   110  	} else {
   111  		// if not cached in memory then hit Redis to get oauth-client from there
   112  		if _, err := k.Spec.OAuthManager.OsinServer.Storage.GetClient(session.OauthClientID); err != nil {
   113  			// set this oauth client as deleted in memory cache for the next N sec
   114  			UtilCache.Set(oauthClientDeletedKey, true, checkOAuthClientDeletedInetrval)
   115  			oauthClientDeleted = true
   116  		} else {
   117  			// set this oauth client as NOT deleted in memory cache for next N sec
   118  			UtilCache.Set(oauthClientDeletedKey, false, checkOAuthClientDeletedInetrval)
   119  		}
   120  	}
   121  	if oauthClientDeleted {
   122  		logger.WithField("oauthClientID", session.OauthClientID).Warning("Attempted access for deleted OAuth client.")
   123  		return errorAndStatusCode(ErrOAuthClientDeleted)
   124  	}
   125  
   126  	// Set session state on context, we will need it later
   127  	switch k.Spec.BaseIdentityProvidedBy {
   128  	case apidef.OAuthKey, apidef.UnsetAuth:
   129  		ctxSetSession(r, &session, accessToken, false)
   130  	}
   131  
   132  	// Request is valid, carry on
   133  	return nil, http.StatusOK
   134  }