Allow multiple authentication - Basic Auth and Bearer Token

Hi Community , @Olu ,

We are trying to have 1 endpoint and allow Basic Auth and Bearer Token keys to authenticate on it.
Right now, I can make it work for Basic Auth, but unable to make the right settings to allow Bearer token.

I’ve seen some examples, here’s what we tried so for regarding the configuration.

(1) [Multiple Authentication mechanisms in Tyk - #2 by ahmet]
This page defines each Authorization config as below.

"auth_configs": {
    "authToken": {
    ...
    },
    "basic": {
    }
}

First question, are these values correct “authToken” and “basic” as key names?
In the “auth_header_name”, my understanding is that it’s a configurable value.

(2) In the multi-authentication page Multiple Auth, there are some values that apparently are required for this configuration and also have a different key. Can someone confirm if those are required?

"To enable this mode you must set the base_identity_provided_by field in your API Definitions to one of the supported chained enums below:

AuthToken
HMACKey
BasicAuthUser
JWTClaim
OIDCUser
OAuthKey
UnsetAuth

You can explicitly set auth token support by setting use_standard_auth to true.
"

So, our API definition was like below:

  {...},
  "base_identity_provided_by": "auth_token",		# is this required? is it the right value?
  "use_basic_auth": true,
  "use_keyless": false,
  "use_standard_auth": true                                   # when I set this to true, basic auth stop working
  "auth": {
    "auth_header_name": "Authorization"
  },
  "auth_configs": {
    "authToken": {                                                    # is authToken the right value here?
      "use_param": false,
      "param_name": "",
      "use_cookie": false,
      "cookie_name": "",
      "auth_header_name": "AuthToken",
      "use_certificate": false,
      "validate_signature": false,
      "signature": {
        "algorithm": "",
        "header": "",
        "secret": "",
        "allowed_clock_skew": 0,
        "error_code": 0,
        "error_message": ""
      }
    },
    "basic": {
      "use_param": false,
      "param_name": "",
      "use_cookie": false,
      "cookie_name": "",
      "auth_header_name": "Authorization",
      "use_certificate": false,
      "validate_signature": false,
      "signature": {
        "algorithm": "",
        "header": "",
        "secret": "",
        "allowed_clock_skew": 0,
        "error_code": 0,
        "error_message": ""
      }
    }
  },
  "definition": {
    "location": "header",
    "key": "x-api-version"
  },
  "version_data": {
    "not_versioned": true,
    "versions": {
      "Default": {
        "name": "v1",
        "use_extended_paths": true
      }
    }
  },
  {...}

Thanks in advance for your help and support.
-Daniel

Basically, what I got so far is it either works with Bearer Token or Basic Auth, if I try to enable both flags use_basic_auth and use_standard_auth, then none of them works. When only one is enabled, then it works fine (either bearer token or basic auth).

Any idea what is wrong with the config?

{
  "name": "demoapi",
  "slug": "demoapi",
  "api_id": "8",
  "org_id": "1",
  "base_identity_provided_by": "auth_token",
  "use_basic_auth": false,  # either use_basic_auth is true
  "use_keyless": false,
  "use_standard_auth": true,  # or use_standard_auth is true. With both, none works.
  "auth_configs": {
    "authToken": {
      "use_param": false,
      "param_name": "",
      "use_cookie": false,
      "auth_header_name": "Authorization",
      "use_certificate": false,
      "signature": {
        "algorithm": "",
        "header": "",
        "secret": "",
        "allowed_clock_skew": 0,
        "error_code": 0,
        "error_message": ""
      }
    },
    "basic": {
      "use_param": false,
      "param_name": "",
      "use_cookie": false,
      "auth_header_name": "Authorization",
      "use_certificate": false,
      "signature": {
        "algorithm": "",
        "header": "",
        "secret": "",
        "allowed_clock_skew": 0,
        "error_code": 0,
        "error_message": ""
      }
    }
  },
  "definition": {
    "location": "header",
    "key": "x-api-version"
  },
  "version_data": {
    "not_versioned": true,
    "versions": {
      "Default": {
        "name": "v1",
        "use_extended_paths": true
      }
    }
  },
  "proxy": {
    "listen_path": "/demoapi/",
    "target_url": "http://demoapi.demoapi.svc.cluster.local/",
    "strip_listen_path": true
  },
  "active": true
}

From what I can see without testing, there seems to be a conflict with the multi authentication. Both have Authorization authentication headers as the auth_header_name.

This could potentially cause what you are experiencing.

If you noticed, the first API definition snippet has different values for auth_header_name

  • AuthToken
  • Authorization

Can you try renaming their values and let us know how it goes.

Hi @Olu , thanks. I believe I tried that, but here’s a detailed information on this attempt:
When I enable basic and standard auth, I get below errors, no matter if using Authorization header and Basic Auth, or if using AuthToken header.

Authorization header:
{
“error”: “Authorization field missing”
}

Using AuthToken header:
{
“error”: “Authorization field missing”
}

These are the logs when I reload tyk’s config:
**pod/gateway-ql-tyk-headless

time="Feb 06 14:14:12" level=debug msg="Initializing API" api_id=8 api_name=demoapi org_id=1
time="Feb 06 14:14:12" level=debug msg=Init api_id=8 api_name=demoapi mw=VersionCheck org_id=1
time="Feb 06 14:14:12" level=debug msg=Init api_id=8 api_name=demoapi mw=RateCheckMW org_id=1
time="Feb 06 14:14:12" level=debug msg=Init api_id=8 api_name=demoapi mw=BasicAuthKeyIsValid org_id=1
time="Feb 06 14:14:12" level=info msg="Checking security policy: Basic" api_id=8 api_name=demoapi org_id=1
time="Feb 06 14:14:12" level=info msg="Checking security policy: Token" api_id=8 api_name=demoapi org_id=1
time="Feb 06 14:14:12" level=debug msg=Init api_id=8 api_name=demoapi mw=AuthKey org_id=1
time="Feb 06 14:14:12" level=debug msg=Init api_id=8 api_name=demoapi mw=KeyExpired org_id=1
time="Feb 06 14:14:12" level=debug msg=Init api_id=8 api_name=demoapi mw=AccessRightsCheck org_id=1
time="Feb 06 14:14:12" level=debug msg=Init api_id=8 api_name=demoapi mw=GranularAccessMiddleware org_id=1
time="Feb 06 14:14:12" level=debug msg=Init api_id=8 api_name=demoapi mw=RateLimitAndQuotaCheck org_id=1
time="Feb 06 14:14:12" level=debug msg=Init api_id=8 api_name=demoapi mw=VersionCheck org_id=1
time="Feb 06 14:14:12" level=debug msg=Init api_id=8 api_name=demoapi mw=KeyExpired org_id=1
time="Feb 06 14:14:12" level=debug msg=Init api_id=8 api_name=demoapi mw=AccessRightsCheck org_id=1
time="Feb 06 14:14:12" level=debug msg="Rate limit endpoint is: /demoapi/tyk/rate-limits" api_id=8 api_name=demoapi org_id=1
time="Feb 06 14:14:12" level=debug msg="Setting Listen Path: /demoapi/" api_id=8 api_name=demoapi org_id=1

API Definition:

{
      "name": "demoapi",
      "slug": "demoapi",
      "api_id": "8",
      "org_id": "1",
      "base_identity_provided_by": "",
      "use_basic_auth": true,
      "use_keyless": false,
      "use_standard_auth": true,
      "auth_configs": {
        "authToken": {
          "use_param": false,
          "param_name": "",
          "use_cookie": false,
          "auth_header_name": "AuthToken",
          "use_certificate": false,
          "signature": {
            "algorithm": "",
            "header": "",
            "secret": "",
            "allowed_clock_skew": 0,
            "error_code": 0,
            "error_message": ""
          }
        },
        "basic": {
          "use_param": false,
          "param_name": "",
          "use_cookie": false,
          "auth_header_name": "Authorization",
          "use_certificate": false,
          "signature": {
            "algorithm": "",
            "header": "",
            "secret": "",
            "allowed_clock_skew": 0,
            "error_code": 0,
            "error_message": ""
          }
        }
      },
      "definition": {
        "location": "header",
        "key": "x-api-version"
      },
      "version_data": {
        "not_versioned": true,
        "versions": {
          "Default": {
            "name": "v1",
            "use_extended_paths": true
          }
        }
      },
      "proxy": {
        "listen_path": "/demoapi/",
        "target_url": "http://demoapi.demoapi.svc.cluster.local:8888/",
        "strip_listen_path": true
      },
      "active": true
    }

Thanks,
Daniel

Was the AuthToken value created with Tyk Key REST API? I don’t have any issues on my end

When I put the 2 headers, it works fine for me

I have attached my policy and snippets of the body when creating both keys

Policy definition

{
  "auth_type": "multiAuth",
  "auth_types": [
      "ba",
      "authToken"
  ],
  "state": "active",
  "graphql_enabled": false,
  "_id": "63e39307975cce0001ded5ff",
  "id": "",
  "name": "Sample Standard Token and Basic Multi Authentication",
  "org_id": "61fd63e8a35fd4000162ed94",
  "rate": 1000,
  "per": 60,
  "quota_max": -1,
  "quota_renewal_rate": -1,
  "throttle_interval": -1,
  "throttle_retry_limit": -1,
  "max_query_depth": -1,
  "access_rights": {
      "c4c2d14d256344687b201d6bd5b15e55": {
          "api_name": "Sample Standard Token and Basic Multi Authentication",
          "api_id": "c4c2d14d256344687b201d6bd5b15e55",
          "versions": [
              "Default"
          ],
          "allowed_urls": [],
          "restricted_types": [],
          "limit": null,
          "field_access_rights": [],
          "allowance_scope": ""
      }
  },
  "hmac_enabled": false,
  "active": true,
  "is_inactive": false,
  "tags": [],
  "key_expires_in": 0,
  "partitions": {
      "quota": true,
      "rate_limit": true,
      "complexity": false,
      "acl": true,
      "per_api": false
  },
  "meta_data": {}
}

Key request for basic auth
POST /tyk/keys/[email protected]

{
	"access_rights": {},
	"alias": "Sample Standard Token and Basic Multi Authentication",
	"allowance": 100,
	"apply_policies": [
		"63e39307975cce0001ded5ff"
	],
	"apply_policy_id": "",
  "basic_auth_data": {
		"password": "1234567",
		"hash_type": "bcrypt"
	},
...
}

Key request for auth token
POST /tyk/keys

{
    "access_rights": {},
	"alias": "",
	"allowance": 100,
	"apply_policies": [
		"63e39307975cce0001ded5ff"
	],
...
}

I’m following the same for keys creation, adding the roles assigned to either the key or the token.
The difference I see is in the policy definition, but I have a question:

Does auth_types require specific value “ba”, or should it be “basic”?
The reason is, at API Definition, I’m calling it as basic. Have a look in the second code block.

All the rest seems the same, any chance you post your api definition pls?

{
  "auth_type": "multiAuth",
  "auth_types": [
      "ba",
      "authToken"
  ],
..}

I tested API definition with use_standard_auth and use_basic_auth flag using all combinations of true/false.
It only works when one is true and the other is false, no matter which. Either Basic Auth works, or Bearer Token works.

Just to confirm, both should be true, right?

      "use_basic_auth": false,
      "use_keyless": false,
      "use_standard_auth": false,
      "auth_configs": {
        "authToken": {
          "use_param": false,
          "param_name": "",
          "use_cookie": false,
          "auth_header_name": "AuthToken",
          "use_certificate": false,
          "signature": {
            "algorithm": "",
            "header": "",
            "secret": "",
            "allowed_clock_skew": 0,
            "error_code": 0,
            "error_message": ""
          }
        },
        "basic": {
          "use_param": false,
          "param_name": "",
          "use_cookie": false,
          "auth_header_name": "Authorization",
          "use_certificate": false,
          "signature": {
            "algorithm": "",
            "header": "",
            "secret": "",
            "allowed_clock_skew": 0,
            "error_code": 0,
            "error_message": ""
          }
        }

Yes both should be true. I will paste my API definition below

{
	"active": true,
	"api_id": "c4c2d14d256344687b201d6bd5b15e55",
	"auth_configs": {
		"authToken": {
			"use_param": false,
			"param_name": "",
			"use_cookie": false,
			"auth_header_name": "AuthToken",
			"use_certificate": false,
			"signature": {
				"algorithm": "",
				"header": "",
				"secret": "",
				"allowed_clock_skew": 0,
				"error_code": 0,
				"error_message": ""
			}
		},
		"basic": {
			"use_param": false,
			"param_name": "",
			"use_cookie": false,
			"auth_header_name": "Authorization",
			"use_certificate": false,
			"signature": {
				"algorithm": "",
				"header": "",
				"secret": "",
				"allowed_clock_skew": 0,
				"error_code": 0,
				"error_message": ""
			}
		}
	},
	"base_identity_provided_by": "",
	"definition": {
		"location": "header",
		"key": "x-api-version"
	},
	"name": "Sample Standard Token and Basic Multi Authentication",
	"proxy": {
		"listen_path": "/multi-auth-basic-and-standard/",
		"target_url": "http://httpbin.org/anything/multi-auth-basic-and-standard",
		"strip_listen_path": true
	},
	"slug": "multi-auth-basic-and-standard",
	"use_basic_auth": true,
	"use_keyless": false,
	"use_standard_auth": true,
	"version_data": {
		"not_versioned": true,
		"versions": {
			"Default": {
				"name": "Default",
				"use_extended_paths": true
			}
		}
	}
}

I actually think you can remove the whole section and it should still work. I tested this myself and it still worked.

I think it’s some legacy code or something related to the commercial dashboard. Because I couldn’t find any reference to it in the open source code.

This worked fine for me

{
	"access_rights": {
		"c4c2d14d256344687b201d6bd5b15e55": {
			"api_name": "Sample Standard Token and Basic Multi Authentication",
			"api_id": "c4c2d14d256344687b201d6bd5b15e55",
			"versions": [
				"Default"
			],
			"allowed_urls": [],
			"restricted_types": [],
			"limit": null,
			"field_access_rights": [],
			"allowance_scope": ""
		}
	},
	"active": true,
	"graphql_enabled": false,
	"hmac_enabled": false,
	"id": "63e39307975cce0001ded5ff",
	"is_inactive": false,
	"key_expires_in": 0,
	"max_query_depth": -1,
	"meta_data": {},
	"name": "Sample Standard Token and Basic Multi Authentication",
	"partitions": {
		"quota": true,
		"rate_limit": true,
		"complexity": false,
		"acl": true,
		"per_api": false
	},
	"per": 60,
	"quota_max": -1,
	"quota_renewal_rate": -1,
	"rate": 1000,
	"state": "active",
	"tags": [],
	"throttle_interval": -1,
	"throttle_retry_limit": -1
}

If you are still having issues then, I would ask you to share your version of the gateway and also double check you are indeed calling the right API. Make sure you don’t have any duplicate API definitions.

For example, having multiple APIs with the same listen path can cause weird behaviors. The first one to load uses the path while subsequent ones have their api_id appended to them to make then unique.

Hi Olu,

Sorry for the late reply. We are currently using 4.0.0.
There’s no duplicate slugs or APIs endpoints, I did try exactly as your setup, but I can only one working at a time. Unless you might be aware of any possible issue on version 4.0.0, then I really don’t know anymore what to try.

/opt/tyk-gateway$ ./tyk --version
v4.0.0

Thanks for your help!

Tested it on version 4.0.0 and got no issues. Can you share a video of your steps?