API endpoint designer whitelisting issue

a) My API should only accept POSTs to its listen path which is /my/auth/myauth/1.0

b) The API functions fine with nothing in endpoint designer

c) I go into endpoint designer and add a POST with path /my/auth/myauth/1.0 and select “whitelist” then update the API

d) Now POSTs to /my/auth/myauth/1.0 are returned with

    "error": "Requested endpoint is forbidden"

e) When I remove this whitelist restriction everything works again

Hi bitsofinfo,

can you share your analytics.conf ?

Kos @ Tyk Support Team

    "listen_port": 3000,
    "tyk_api_config": {
        "Host": "http://tyk_gateway",
        "Port": "8080",
        "Secret": "352d20ee67be67f6340b4c0605b044b7"
    "mongo_url": "mongodb://mongo:27017/tyk_analytics",
    "page_size": 10,
    "admin_secret": "12345",
    "shared_node_secret": "352d20ee67be67f6340b4c0605b044b7",
    "redis_port": 6379,
    "redis_host": "redis",
    "redis_password": "",
    "enable_cluster": false,
    "force_api_defaults": false,
    "notify_on_change": true,
    "license_key": "x.eyJhbGxvd2VkX25vZGVzIjoiMmFmZjIzZxxw",
    "redis_database": 0,
    "redis_hosts": null,
    "hash_keys": true,
   "email_backend": {
        "enable_email_notifications": false,
        "code": "",
        "settings": null,
        "default_from_email": "",
        "default_from_name": ""
    "hide_listen_path": false,
    "sentry_code": "",
    "sentry_js_code": "",
    "use_sentry": false,
    "enable_master_keys": false,
    "enable_duplicate_slugs": true,
    "show_org_id": true,
    "host_config": {
        "enable_host_names": false,
        "disable_org_slug_prefix": true,
        "hostname": "",
        "override_hostname": "www.tyk-portal-test.com",
        "portal_domains": {},
        "portal_root_path": "/portal"
"http_server_options": {
        "use_ssl": false,
        "certificates": [
                "domain_name": "",
                "cert_file": "",
                "key_file": ""
        "min_version": 0
    "ui": {
        "login_page": {},
        "nav": {},
        "uptime": {},
        "portal_section": null,
        "designer": {},
        "dont_show_admin_sockets": false,
        "dont_allow_license_management": false,
        "dont_allow_license_management_view": false
    "home_dir": "/opt/tyk-dashboard",
 "identity_broker": {
        "enabled": false,
        "host": {
            "connection_string": "",
            "secret": ""
    "tagging_options": {
        "tag_all_apis_by_org": false

Hi bitsofinfo,

sorry, can you also share the API definition ?

Kos @ Tyk Support Team

    "id": "5981ea4cb46f2e000105f240",
    "name": "/my/auth/myauth/1.0",
    "slug": "my/auth/myauth/10",
    "api_id": "3b30b68340b8492858ea00be8c9b248e",
    "org_id": "5976507eb46f2e00016bb4a1",
    "use_keyless": false,
    "use_oauth2": false,
    "use_openid": false,
    "openid_options": {
        "providers": [],
        "segregate_by_client": false
    "oauth_meta": {
        "allowed_access_types": [],
        "allowed_authorize_types": [],
        "auth_login_redirect": ""
    "auth": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "x-internal-authorization"
    "use_basic_auth": false,
    "enable_jwt": false,
    "use_standard_auth": true,
    "enable_coprocess_auth": false,
    "jwt_signing_method": "",
    "jwt_source": "",
    "jwt_identity_base_field": "",
    "jwt_client_base_field": "",
    "jwt_policy_field_name": "",
    "notifications": {
        "shared_secret": "",
        "oauth_on_keychange_url": ""
    "enable_signature_checking": false,
    "hmac_allowed_clock_skew": -1,
    "base_identity_provided_by": "",
    "definition": {
        "location": "header",
        "key": "x-api-version"
    "version_data": {
        "not_versioned": true,
        "versions": {
            "Default": {
                "name": "Default",
                "expires": "",
                "paths": {
                    "ignored": [],
                    "white_list": [],
                    "black_list": []
                "use_extended_paths": true,
                "extended_paths": {
                    "white_list": [
                            "path": "/my/auth/myauth/1.0",
                            "method_actions": {
                                "POST": {
                                    "action": "no_action",
                                    "code": 200,
                                    "data": "",
                                    "headers": {}
                "global_headers": {},
                "global_headers_remove": [],
                "global_size_limit": 0,
                "override_target": ""
    "uptime_tests": {
        "check_list": [],
        "config": {
            "expire_utime_after": 0,
            "service_discovery": {
                "use_discovery_service": false,
                "query_endpoint": "",
                "use_nested_query": false,
                "parent_data_path": "",
                "data_path": "",
                "port_data_path": "",
                "target_path": "",
                "use_target_list": false,
                "cache_timeout": 60,
                "endpoint_returns_list": false
            "recheck_wait": 0
    "proxy": {
        "preserve_host_header": false,
        "listen_path": "/my/auth/myauth/1.0",
        "target_url": "",
        "strip_listen_path": true,
        "enable_load_balancing": false,
        "target_list": [],
        "check_host_against_uptime_tests": false,
        "service_discovery": {
            "use_discovery_service": false,
            "query_endpoint": "",
            "use_nested_query": false,
            "parent_data_path": "",
            "data_path": "hostname",
            "port_data_path": "port",
            "target_path": "/api-slug",
            "use_target_list": false,
            "cache_timeout": 60,
            "endpoint_returns_list": false
    "disable_rate_limit": false,
    "disable_quota": false,
    "custom_middleware": {
        "pre": [
                "name": "soapOpExtractor",
                "path": "middleware/soapOpExtractor.js",
                "require_session": false
                "name": "myAuth",
                "path": "middleware/myAuth.js",
                "require_session": false
        "post": [],
        "post_key_auth": [],
        "auth_check": {
            "name": "",
            "path": "",
            "require_session": false
        "response": [],
        "driver": "",
        "id_extractor": {
            "extract_from": "",
            "extract_with": "",
            "extractor_config": {}
    "custom_middleware_bundle": "",
    "cache_options": {
        "cache_timeout": 60,
        "enable_cache": true,
        "cache_all_safe_requests": false,
        "cache_response_codes": [],
        "enable_upstream_cache_control": false
    "session_lifetime": 0,
    "active": true,
    "auth_provider": {
        "name": "",
        "storage_engine": "",
        "meta": {}
    "session_provider": {
        "name": "",
        "storage_engine": "",
        "meta": null
    "event_handlers": {
        "events": {}
    "enable_batch_request_support": false,
    "enable_ip_whitelisting": false,
    "allowed_ips": [],
    "dont_set_quota_on_create": false,
    "expire_analytics_after": 0,
    "response_processors": [],
    "CORS": {
        "enable": false,
        "allowed_origins": [],
        "allowed_methods": [],
        "allowed_headers": [],
        "exposed_headers": [],
        "allow_credentials": false,
        "max_age": 24,
        "options_passthrough": false,
        "debug": false
    "domain": "",
    "do_not_track": false,
    "tags": [],
    "enable_context_vars": false,
    "config_data": {
        "api_id": "3b30b68340b8492858ea00be8c9b248e",
        "api_name": "/my/auth/myauth/1.0",
        "debug_mode": "true",
        "test_host": "",
        "org_id": "5976507eb46f2e00016bb4a1",
        "p_system_host": "tyk-test-auth",
        "r_resource_tags": "test,#test",
        "r_system": "test",
        "rrt_from_header_name": "X-test",
        "rrt_postfix": "",
        "rrt_prefix": "ddd-ws-test-test-",
        "session_expires_seconds": "60",
        "session_key_include_headers": "X-test",
        "soap_operation_header_name": "X-test",
        "strip_authorization_header": "true",
        "strip_soap_op_namespace": "true"

you have the path you are trying to protect as your listen path, so the white list will not match because it’s looking for that setting after the listen path.

Tyk does this:

Match the apinto the listen path
Strip thatbpath from the URL
Pass the remainder to the whitelist
Whitelist will try to match against the remainder

So, either disable the strip listen path
Or change the listen path to something totally different and prepend it to you r request URL (and keep the strip)
Or make the listen path root (/) (and keep the strip)

That’s basically it, you need to find a combination of listen path and URL that yu are happy with, and decide whether you want to host the api on a soecial path of the gateway or not (e.g. /login/).

For example, you could make the listen path /login/, the target http://server:port/auth/my/auth/blah and then white list root (/)

There’s lots of combinations :-/

So if I have two versions of an API such as

The payload is just POSTed to the /version

And I need to ensure that both are restricted to POST exclusively.

So given the way this works I’d have to define ONE API that listens on http://whatever/my/test/service/ w/ a POST whitelist for 1.0 and 2.0, followed by a URLRewrite going to backendA vs backendB?

In other words there is no way to define these a separate API defs with such a POST restriction/whitelist because they both share the same host/listen path…

Or you could enabke versioning and version the api with v1 and v2 as url elements (they must be the first item after the listen path). Each version can have its own target. Then you have one api, one listen path, two versions, two targets, two separate endpoint designer sets.

Then you just whitelist the root.

Yeah just can’t do that, I’m having to evaluate porting some pre-existing URI patterns to see if Tyk can support it.

But you can:

listen path:/my/test/service/
Version1: 1.0
Version2: 2.0

So the path for auth 1 is :/my/test/service/1.0
And auth2 is: :/my/test/service/2.0

Then set the override endpoint in the versioning screen To backendA and backendB respectively
Then add whitelist 1.0 POST and 2.0 POST (version strings are not stripped from the listen path)

Your URL pattern is unchanged, you’ve versioned your API properly in the API manager and you can send requests to different back ends.

Or, you do the re-write as you originally suggested.

ok, what do I specify for “Version data location”, none of the options are applicable.

But the first url element is /my, not 1.0, or are you saying this is post strip?

If /my is part of eh listen path, then this is post strip

Ok. I’ve tried this to no avail

  • Listen path /my/auth/myauth, w/ strip enabled

  • Versions enabled, “First URL element” selected

  • Have 2 versions listed 1.0 -> backendA… 2.0 -> backendB

Make a request to either /my/auth/myauth/1.0 or /my/auth/myauth/2.0 and client gets back

    "error": "Version information not found"
2017-08-07T15:55:18.920926507Z time="Aug  7 15:55:18" level=error msg="request error: Version information not found" api_id=0b73f4aaf2db4a93538df302a86dcc7f org_id=5976507eb46f2e00016bb4a1 path="1.0" server_name="" user_id= user_ip=

2017-08-07T15:55:18.920926507Z time="Aug  7 15:55:18" level=error msg="request error: Version information not found" api_id=0b73f4aaf2db4a93538df302a86dcc7f org_id=5976507eb46f2e00016bb4a1 path="2.0" server_name="" user_id= user_ip=

Really could use some help on this, anyone?

Ah, you might need to add something to the end of that URL like /login. Maybe this isn’t an option for you

You mean like change the published URL to /my/auth/myauth/2.0/[something]?

Yeah can’t do that, these are published URIs I need to migrate from another kind of gateway to Tyk

Is this a bug? Why wouldn’t this work?

Because of how URL versioning is handled, it searched for the first version reference within two slashes - we may need to make it more lax.