github.com/TykTechnologies/tyk/ee/middleware/upstreamoauth
No package summary is available.
Package
Files: 6. Third party imports: 3. Imports from organisation: 0. Tests: 0. Benchmarks: 0.
Constants
const (
MiddlewareName = "UpstreamOAuth"
ClientCredentialsAuthorizeType = "clientCredentials"
PasswordAuthorizeType = "password"
)
Vars
var (
ctxData = httpctx.NewValue[map[string]any](ctx.ContextData)
CtxGetData = ctxData.Get
CtxSetData = ctxData.Set
)
Middleware implements model.Middleware.
var _ model.Middleware = &Middleware{}
Types
BaseMiddleware
BaseMiddleware is the subset of BaseMiddleware APIs that the middleware uses.
| Field name | Field type | Comment |
|---|---|---|
| type |
|
No comment on field. |
type BaseMiddleware interface {
model.LoggerProvider
FireEvent(name apidef.TykEvent, meta interface{})
}
Cache
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| type |
|
No comment on field. |
type Cache interface {
// GetToken returns the token from cache or issues a request to obtain it from the OAuth provider.
GetToken(r *http.Request) (string, error)
// ObtainToken issues a request to obtain the token from the OAuth provider.
ObtainToken(ctx context.Context) (*oauth2.Token, error)
}
ClientCredentialsClient
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| mw |
|
No comment on field. |
type ClientCredentialsClient struct {
mw *Middleware
}
ClientCredentialsOAuthProvider
This type doesn't have documentation.
type ClientCredentialsOAuthProvider struct{}
EventUpstreamOAuthMeta
EventUpstreamOAuthMeta is the metadata structure for an upstream OAuth event
| Field name | Field type | Comment |
|---|---|---|
|
No comment on field. | |
| APIID |
|
No comment on field. |
type EventUpstreamOAuthMeta struct {
model.EventMetaDefault
APIID string
}
Gateway
Gateway is the subset of Gateway APIs that the middleware uses.
| Field name | Field type | Comment |
|---|---|---|
| type |
|
No comment on field. |
type Gateway interface {
model.ConfigProvider
}
Middleware
Middleware implements upstream OAuth middleware.
| Field name | Field type | Comment |
|---|---|---|
| Spec |
|
No comment on field. |
| Gw |
|
No comment on field. |
| Base |
|
No comment on field. |
| clientCredentialsStorageHandler |
|
No comment on field. |
| passwordStorageHandler |
|
No comment on field. |
type Middleware struct {
Spec model.MergedAPI
Gw Gateway
Base BaseMiddleware
clientCredentialsStorageHandler Storage
passwordStorageHandler Storage
}
OAuthHeaderProvider
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| type |
|
No comment on field. |
type OAuthHeaderProvider interface {
// getOAuthToken returns the OAuth token for the request.
getOAuthToken(r *http.Request, mw *Middleware) (string, error)
// getHeaderName returns the header name for the OAuth token.
getHeaderName(mw *Middleware) string
//
headerEnabled(mw *Middleware) bool
}
PasswordClient
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| mw |
|
No comment on field. |
type PasswordClient struct {
mw *Middleware
}
PasswordOAuthProvider
This type doesn't have documentation.
type PasswordOAuthProvider struct{}
PerAPIClientCredentialsOAuthProvider
This type doesn't have documentation.
type PerAPIClientCredentialsOAuthProvider struct{}
Provider
Provider implements upstream auth provider.
| Field name | Field type | Comment |
|---|---|---|
| Logger |
|
Logger is the logger to be used. |
| HeaderName |
|
HeaderName is the header name to be used to fill upstream auth with. |
| AuthValue |
|
AuthValue is the value of auth header. |
type Provider struct {
// Logger is the logger to be used.
Logger *logrus.Entry
// HeaderName is the header name to be used to fill upstream auth with.
HeaderName string
// AuthValue is the value of auth header.
AuthValue string
}
Storage
Type Storage is a subset of storage.RedisCluster
| Field name | Field type | Comment |
|---|---|---|
| type |
|
No comment on field. |
type Storage interface {
GetKey(key string) (string, error)
SetKey(string, string, int64) error
Lock(key string, timeout time.Duration) (bool, error)
}
TokenData
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| Token |
|
No comment on field. |
| ExtraMetadata |
|
No comment on field. |
type TokenData struct {
Token string `json:"token"`
ExtraMetadata map[string]interface{} `json:"extra_metadata"`
}
Functions
func BuildMetadataMap
func BuildMetadataMap(token *oauth2.Token, extraMetadataKeys []string) map[string]interface{} {
metadataMap := make(map[string]interface{})
for _, key := range extraMetadataKeys {
if val := token.Extra(key); val != "" && val != nil {
metadataMap[key] = val
}
}
return metadataMap
}
Cognitive complexity: 7, Cyclomatic complexity: 4
func CreateTokenDataBytes
func CreateTokenDataBytes(encryptedToken string, token *oauth2.Token, extraMetadataKeys []string) ([]byte, error) {
td := TokenData{
Token: encryptedToken,
ExtraMetadata: BuildMetadataMap(token, extraMetadataKeys),
}
return json.Marshal(td)
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func NewMiddleware
NewMiddleware returns a new instance of Middleware.
func NewMiddleware(gw Gateway, mw BaseMiddleware, spec model.MergedAPI, ccStorageHandler Storage, pwStorageHandler Storage) *Middleware {
return &Middleware{
Base: mw,
Gw: gw,
Spec: spec,
clientCredentialsStorageHandler: ccStorageHandler,
passwordStorageHandler: pwStorageHandler,
}
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func NewOAuthHeaderProvider
func NewOAuthHeaderProvider(oauthConfig apidef.UpstreamOAuth) (OAuthHeaderProvider, error) {
if !oauthConfig.IsEnabled() {
return nil, fmt.Errorf("upstream OAuth is not enabled")
}
switch {
case len(oauthConfig.AllowedAuthorizeTypes) == 0:
return nil, fmt.Errorf("no OAuth configuration selected")
case len(oauthConfig.AllowedAuthorizeTypes) > 1:
return nil, fmt.Errorf("both client credentials and password authentication are provided")
case oauthConfig.AllowedAuthorizeTypes[0] == ClientCredentialsAuthorizeType:
return &ClientCredentialsOAuthProvider{}, nil
case oauthConfig.AllowedAuthorizeTypes[0] == PasswordAuthorizeType:
return &PasswordOAuthProvider{}, nil
default:
return nil, fmt.Errorf("no valid OAuth configuration provided")
}
}
Cognitive complexity: 10, Cyclomatic complexity: 7
func SetExtraMetadata
func SetExtraMetadata(r *http.Request, keyList []string, metadata map[string]interface{}) {
contextDataObject := CtxGetData(r)
if contextDataObject == nil {
contextDataObject = make(map[string]interface{})
}
for _, key := range keyList {
if val, ok := metadata[key]; ok && val != "" {
contextDataObject[key] = val
}
}
CtxSetData(r, contextDataObject)
}
Cognitive complexity: 9, Cyclomatic complexity: 5
func UnmarshalTokenData
func UnmarshalTokenData(tokenData string) (TokenData, error) {
var tokenContents TokenData
err := json.Unmarshal([]byte(tokenData), &tokenContents)
if err != nil {
return TokenData{}, fmt.Errorf("failed to unmarshal token data: %w", err)
}
return tokenContents, nil
}
Cognitive complexity: 3, Cyclomatic complexity: 2
func (*ClientCredentialsClient) GetToken
func (cache *ClientCredentialsClient) GetToken(r *http.Request) (string, error) {
cacheKey := generateClientCredentialsCacheKey(cache.mw.Spec.UpstreamAuth.OAuth, cache.mw.Spec.APIID)
secret := cache.mw.Gw.GetConfig().Secret
extraMetadata := cache.mw.Spec.UpstreamAuth.OAuth.ClientCredentials.ExtraMetadata
obtainTokenFunc := func(ctx context.Context) (*oauth2.Token, error) {
return cache.ObtainToken(ctx)
}
return getToken(r, cacheKey, obtainTokenFunc, secret, extraMetadata, cache.mw.clientCredentialsStorageHandler)
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func (*ClientCredentialsClient) ObtainToken
func (cache *ClientCredentialsClient) ObtainToken(ctx context.Context) (*oauth2.Token, error) {
cfg := newOAuth2ClientCredentialsConfig(cache.mw)
tokenSource := cfg.TokenSource(ctx)
return tokenSource.Token()
}
Cognitive complexity: 0, Cyclomatic complexity: 1
func (*Middleware) EnabledForSpec
EnabledForSpec checks if streaming is enabled on the config.
func (m *Middleware) EnabledForSpec() bool {
if !m.Spec.UpstreamAuth.IsEnabled() {
return false
}
if !m.Spec.UpstreamAuth.OAuth.Enabled {
return false
}
return true
}
Cognitive complexity: 4, Cyclomatic complexity: 3
func (*Middleware) FireEvent
FireEvent emits an upstream OAuth event with an optional custom message.
func (mw *Middleware) FireEvent(r *http.Request, e event.Event, message string, apiId string) {
if message == "" {
message = event.String(e)
}
mw.Base.FireEvent(e, EventUpstreamOAuthMeta{
EventMetaDefault: model.NewEventMetaDefault(r, message),
APIID: apiId,
})
}
Cognitive complexity: 3, Cyclomatic complexity: 2
func (*Middleware) Init
Init initializes the middleware.
func (m *Middleware) Init() {
m.Logger().Debug("Initializing Upstream basic auth Middleware")
}
Cognitive complexity: 0, Cyclomatic complexity: 1
func (*Middleware) Logger
Logger returns a logger with middleware filled out.
func (m *Middleware) Logger() *logrus.Entry {
return m.Base.Logger().WithField("mw", m.Name())
}
Cognitive complexity: 0, Cyclomatic complexity: 1
func (*Middleware) Name
Name returns the name for the middleware.
func (m *Middleware) Name() string {
return MiddlewareName
}
Cognitive complexity: 0, Cyclomatic complexity: 1
func (*Middleware) ProcessRequest
ProcessRequest will handle upstream OAuth.
func (m *Middleware) ProcessRequest(_ http.ResponseWriter, r *http.Request, _ interface{}) (error, int) {
provider, err := NewOAuthHeaderProvider(m.Spec.UpstreamAuth.OAuth)
if err != nil {
return fmt.Errorf("failed to get OAuth header provider: %w", err), http.StatusInternalServerError
}
payload, err := provider.getOAuthToken(r, m)
if err != nil {
return fmt.Errorf("failed to get OAuth token: %w", err), http.StatusInternalServerError
}
upstreamOAuthProvider := Provider{
HeaderName: header.Authorization,
AuthValue: payload,
Logger: m.Logger(),
}
headerName := provider.getHeaderName(m)
if headerName != "" {
upstreamOAuthProvider.HeaderName = headerName
}
if provider.headerEnabled(m) {
headerName := provider.getHeaderName(m)
if headerName != "" {
upstreamOAuthProvider.HeaderName = headerName
}
}
core.SetUpstreamAuth(r, upstreamOAuthProvider)
return nil, http.StatusOK
}
Cognitive complexity: 12, Cyclomatic complexity: 6
func (*Middleware) Unload
func (m *Middleware) Unload() {
// nothing to do here
}
Cognitive complexity: 0, Cyclomatic complexity: 1
func (*PasswordClient) GetToken
func (cache *PasswordClient) GetToken(r *http.Request) (string, error) {
cacheKey := generatePasswordOAuthCacheKey(cache.mw.Spec.UpstreamAuth.OAuth, cache.mw.Spec.APIID)
secret := cache.mw.Gw.GetConfig().Secret
extraMetadata := cache.mw.Spec.UpstreamAuth.OAuth.PasswordAuthentication.ExtraMetadata
obtainTokenFunc := func(ctx context.Context) (*oauth2.Token, error) {
return cache.ObtainToken(ctx)
}
return getToken(r, cacheKey, obtainTokenFunc, secret, extraMetadata, cache.mw.passwordStorageHandler)
}
Cognitive complexity: 1, Cyclomatic complexity: 1
func (*PasswordClient) ObtainToken
func (cache *PasswordClient) ObtainToken(ctx context.Context) (*oauth2.Token, error) {
cfg := newOAuth2PasswordConfig(cache.mw)
return cfg.PasswordCredentialsToken(ctx, cache.mw.Spec.UpstreamAuth.OAuth.PasswordAuthentication.Username, cache.mw.Spec.UpstreamAuth.OAuth.PasswordAuthentication.Password)
}
Cognitive complexity: 0, Cyclomatic complexity: 1
func (Provider) Fill
Fill sets the request's HeaderName with AuthValue
func (u Provider) Fill(r *http.Request) {
if r.Header.Get(u.HeaderName) != "" {
u.Logger.WithFields(logrus.Fields{
"header": u.HeaderName,
}).Info("Authorization header conflict detected: Client header overwritten by Gateway upstream authentication header.")
}
r.Header.Set(u.HeaderName, u.AuthValue)
}
Cognitive complexity: 3, Cyclomatic complexity: 2
Private functions
func generateClientCredentialsCacheKey
generateClientCredentialsCacheKey (config apidef.UpstreamOAuth, apiId string) string
References: fmt.Sprintf, hex.EncodeToString, sha256.New, strings.Join.
func generatePasswordOAuthCacheKey
generatePasswordOAuthCacheKey (config apidef.UpstreamOAuth, apiId string) string
References: fmt.Sprintf, hex.EncodeToString, sha256.New, strings.Join.
func getToken
getToken (r *http.Request, cacheKey string, obtainTokenFunc func(context.Context) (*oauth2.Token, error), secret string, extraMetadata []string, cache Storage) (string, error)
References: crypto.Decrypt, crypto.Encrypt, crypto.GetPaddedString, time.Until.
func handleOAuthError
handleOAuthError (r *http.Request, mw *Middleware, err error) (string, error)
References: event.UpstreamOAuthError.
func newOAuth2ClientCredentialsConfig
newOAuth2ClientCredentialsConfig (OAuthSpec *Middleware) oauth2clientcredentials.Config
References: oauth2clientcredentials.Config.
func newOAuth2PasswordConfig
newOAuth2PasswordConfig (OAuthSpec *Middleware) oauth2.Config
References: oauth2.Config, oauth2.Endpoint.
func retryGetKeyAndLock
retryGetKeyAndLock (cacheKey string, cache Storage) (string, error)
References: fmt.Errorf, time.Millisecond, time.Second, time.Sleep.
func setTokenInCache
setTokenInCache (cache Storage, cacheKey string, token string, ttl time.Duration) error
References: time.Now, time.Until.
func getHeaderName
getHeaderName (OAuthSpec *Middleware) string
func getOAuthToken
getOAuthToken (r *http.Request, mw *Middleware) (string, error)
References: fmt.Sprintf.
func headerEnabled
headerEnabled (OAuthSpec *Middleware) bool
func getHeaderName
getHeaderName (OAuthSpec *Middleware) string
func getOAuthToken
getOAuthToken (r *http.Request, mw *Middleware) (string, error)
References: fmt.Sprintf.
func headerEnabled
headerEnabled (OAuthSpec *Middleware) bool
Tests
Files: 1. Third party imports: 2. Imports from organisation: 0. Tests: 6. Benchmarks: 0.
Constants
const ClientCredentialsAuthorizeType = upstreamoauth.ClientCredentialsAuthorizeType
const PasswordAuthorizeType = upstreamoauth.PasswordAuthorizeType
Vars
var StartTest = gateway.StartTest
Types
APISpec
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| type |
|
No comment on field. |
type APISpec = gateway.APISpec