Enable CORS for Tyk Gateway API

Hi,

  Need some help here, I'm trying to built a prototype and run everything on the same laptop. 

 How do I configure to enable CORS for Tyk Gateway built-in API? I'm getting error from the the JS in the html page that is the API.

 **Error:**
       [Error] Preflight response is not successful
       [Error] Fetch API cannot load http://localhost:8080/tyk/apis due to access control checks.
       [Error] Failed to load resource: Preflight response is not successful (apis, line 0)
 I'm trying to call the following Tyk built-in API to get the list of registered APIs:
 /tyk/apis

When I check "Disable Cross-Origin Restrictions" through Safari's developer menu I was able to get the list successfully. 

 Thanks in advance.

Hi,

Unfortunately the management APIs in the gateway are not setup to provide suitable CORS responses, so will not provide the relevant headers for preflight or similar checks.

Can I ask what you are attempting to achieve, as it seems to imply you have the gateway secret stored in a single page app or similar, which is not the best approach for security, as the gateway secret being available on the client end, means users could access any and all admin apis on the gateway. I’m wondering if there is a better way to achieve your ends.

For example if you really needed to access this management API, you could define an API in the gateway that uses the /tyk/apis endpoint as its upstream, then you can enable CORS in the API Definition, and also make use of its authentication controls, and at the same time, not expose the Gateway secret to the client app.

Best Regards,
Chris

Hi @chris.f

 Thanks for the quick response and assistance. That's a great idea.

 But how do I pass the secret key through the API definition? 

Thank you in advance.

Hi @kamikazane, you can use inject/request headers

Hi @Olu

Thanks. I tried but I’m still getting error. Can help to enlighten what I might have done wrongly? I had tried also changing the host.docker.internal to localhost and still getting the error.

Error:

{“status”:“error”,“message”:“Attempted administrative access with invalid or missing key!”}

API Definition:

{
  "name": "Get API Config List",
  "slug": "get-api-config-list",
  "api_id": "71",
  "org_id": "1",
  "use_keyless": true,
  "definition": {
    "location": "header",
    "key": "x-api-version"
  },
  "version_data": {
    "not_versioned": true,
    "versions": {
       "Default": {
         "name": "Default",
         "use_extended_paths" :true
       }
     }
  },
  "CORS": {
    "enable": true,
    "allowed_origins": [
       "http://host.docker.internal:8080"
    ],
    "allowed_methods": [],
    "allowed_headers": [],
    "exposed_headers": [],
    "allowed_credentials": false,
    "max_age": 24,
    "options_passthrough": false,
    "debug": false
  },
  "extended_paths": {
    "transform_headers": [
      {
        "add_headers": { "x-tyk-authorization": "foo" }
      }
    ]
  },
  "proxy": {
    "listen_path": "/api/getAPIConfigList",
    "target_url": "http://host.docker.internal:8080/tyk/apis",
    "strip_listen_path": true
  },
  "active": true
}

I can observe there is a mix-up between global headers and path based headers. You seem to be missing extra information when specifying a path based header. You omitted the Path and Method for the header the and have only added the Key and Value for the header.

"transform_headers": [
    {
      "add_headers": {"x-tyk-authorization": "foo"},
      "path": "API PATH/SUB PATH",
      "method": "YOUR HTTP METHOD GOES HERE"
    }
  ]

You can also use the global_headers, but this means that all API calls regardless of the sub path get injected with the header. This may not be ideal.

"global_headers": {
      "x-tyk-authorization": "foo",
}

Hi @Olu

Thanks for your kind assistance, appreciate it. Tried the following and still getting the same error.

Any idea or further advice? Thanks

{
  "name": "Get API Config List",
  "slug": "get-api-config-list",
  "api_id": "71",
  "org_id": "1",
  "use_keyless": true,
  "definition": {
    "location": "header",
    "key": "x-api-version"
  },
  "version_data": {
    "not_versioned": true,
    "versions": {
       "Default": {
         "name": "Default",
         "use_extended_paths" :true
       }
     }
  },
  "CORS": {
    "enable": true,
    "allowed_origins": [
       "http://localhost:8080"
    ],
    "allowed_methods": [],
    "allowed_headers": [],
    "exposed_headers": [],
    "allowed_credentials": false,
    "max_age": 24,
    "options_passthrough": false,
    "debug": false
  },
  "extended_paths": {
    "transform_headers": [
      {
        "add_headers": { "x-tyk-authorization": "foo" },
        "path": "/api/getAPIConfigList",
        "method": "GET"
      }
    ]
  },
  "proxy": {
    "listen_path": "/api/getAPIConfigList",
    "target_url": "http://localhost:8080/tyk/apis",
    "strip_listen_path": true
  },
  "active": true
}

Hi @kamikazane, there were 2 things wrong.

First is the structure of the API def was off. extended_paths is a child of the version and not at the root. You can find a sample structure of the API definition here

Second was the value of path property in the transform_headers is actually a subpath and not {{ path / subpath }}, like I shared earlier. In your case, making it the root should work.

I have pasted the API definition that should work for your environment. Please check the values are accurate and try again

{
  "name": "Get API Config List",
  "slug": "get-api-config-list",
  "api_id": "71",
  "org_id": "1",
  "use_keyless":true,
  "definition": {
    "location": "header",
    "key": "x-api-version"
  },
  "version_data": {
    "not_versioned": true,
    "versions": {
      "Default": {
        "use_extended_paths": true,
				"extended_paths": {
					"transform_headers": [
						{
							"delete_headers": [],
							"add_headers": { 
								"x-tyk-authorization": "foo" 
							},
							"path": "/",
							"method": "GET"
						}
					]
				}
			}
		}
  },
	"CORS": {
    "enable": true,
    "allowed_origins": [
       "http://localhost:8080"
    ],
    "allowed_methods": [],
    "allowed_headers": [],
    "exposed_headers": [],
    "allowed_credentials": false,
    "max_age": 24,
    "options_passthrough": false,
    "debug": false
  },
  "proxy": {
    "listen_path": "/api/getAPIConfigList",
    "target_url": "http://localhost:8080/tyk/apis",
    "strip_listen_path": true
  },
  "active": true
}

Hi @Olu

Thank you so much for your kind help. I tried the API definition you had given but it is still throwing the same error. I tried to set the global_headers and it’s working. Not sure what went wrong and it could be my silly mistake again. Any idea what might be missing or mistakes made?

The API definition as follows:


{
  "name": "Get API Config List",
  "slug": "get-api-config-list",
  "api_id": "71",
  "org_id": "1",
  "use_keyless": true,
  "definition": {
    "location": "header",
    "key": "x-api-version"
  },
  "version_data": {
    "not_versioned": true,
    "versions": {
       "Default": {
         "name": "Default",
         "use_extended_paths" :true,
         "extended_paths": {
           "tranform_headers": [
             {
               "delete_headers": [],
               "add_headers": {
                 "x-tyk-authorization": "foo"
               },
               "path": "/",
               "method": "GET"
             }
           ]
         }
       }
     }
  },
  "CORS": {
    "enable": true,
    "allowed_origins": [
       "http://localhost:8080"
    ],
    "allowed_methods": [],
    "allowed_headers": [],
    "exposed_headers": [],
    "allowed_credentials": false,
    "max_age": 24,
    "options_passthrough": false,
    "debug": false
  },
  "proxy": {
    "listen_path": "/api/getAPIConfigList",
    "target_url": "http://localhost:8080/tyk/apis",
    "strip_listen_path": true
  },
  "active": true
}

Looks like your tranform_headers is missing an s in between n and f

Hi @Olu

You are spot on. It’s really my silly mistake once again. Really appreciate your kind help and patience.

It’s working like a charm now.

Thank you once again.

Glad to hear that. Happy to know I could help.