OAuth authorizing not working after upgrade

Hi,

I’ve been running an older version of Tyk (not sure which, but with the older Dashboard design) in Docker for some time. I set up OAuth key authorization using the guide in the documentation (https://tyk.io/docs/security/your-apis/oauth-2-0/) and it’s been working fine.

This week I upgraded to the latest version, and the OAuth flow is no longer working. Here is the (javascript) code that was previously working fine:

return request({
                        method: 'POST',
                        uri: 'http://tyk_gateway:80/tyk/oauth/authorize-client/',
                        headers: {
                            'Content-Type': 'application/x-www-form-urlencoded',
                            'x-tyk-authorization': TYK_SECRET,
                        },
                        form: {
                            client_id: req.query.client_id,
                            redirect_uri: req.query.redirect_uri,
                            response_type: req.query.response_type,
                            state: req.query.state,
                            key_rules: JSON.stringify({
                                alias: data.token,
                                meta_data: {
                                    user_id: data.user_id,
                                    created: data.created,
                                },
                            }),
                        },
                    });

This is no longer generating a key as before, but instead throws a 404 error ('404 - "404 page not found\\n"').

The guide in the manual is still the same, so I wouldn’t have thought anything had changed. Something may have broken in the upgrade process (where I deleted Docker images, containers and volumes, and rebuilt from scratch, then imported the same API configuration using JSON).

Any ideas what might be causing this?

Thanks!

/tyk/oauth/authorize-client/ is a special path relative to your API listen path. So check if your Listen path is “/”.

Another reason why it can give 404, is if you set your API domain or set “hostname” in tyk.conf and calling url with wrong domain. Check it.

When API loading to tyk, check the logs to ensure that API actually loaded?

If none of this helps, attach your config and api definition.

Thanks for your suggestions, @leon. I’ve tried to change the domain in the request from javascript, but it didn’t help. I’ve also tried a simple curl http://tyk_gateway/orgs/1 (from within the container running the javascript code above), which is an API endpoint of mine, and it works. So there seems to be no problem making requests from there in general, or for Tyk to handle/route the API request correctly using that domain and path.

This is my tyk.conf:

{
    "listen_port": 80,
    "secret": "actually-something-else",
    "node_secret": "actually-something-else",
    "template_path": "/opt/tyk-gateway/templates",
    "tyk_js_path": "/opt/tyk-gateway/js/tyk.js",
    "middleware_path": "/opt/tyk-gateway/middleware",
    "use_db_app_configs": true,
    "db_app_conf_options": {
        "connection_string": "http://tyk_dashboard:3000",
        "node_is_segmented": false,
        "tags": ["test2"]
    },
    "app_path": "/opt/tyk-gateway/apps/",
    "storage": {
        "type": "redis",
        "host": "redis",
        "port": 6379,
        "username": "",
        "password": "",
        "database": 0,
        "optimisation_max_idle": 100
    },
    "enable_analytics": true,
    "analytics_config": {
        "type": "mongo",
        "csv_dir": "/tmp",
        "mongo_url": "",
        "mongo_db_name": "",
        "mongo_collection": "",
        "purge_delay": -1,
        "ignored_ips": []
    },
    "health_check": {
        "enable_health_checks": true,
        "health_check_value_timeouts": 60
    },
    "optimisations_use_async_session_write": true,
    "proxy_default_timeout": 300,
    "enable_non_transactional_rate_limiter": true,
    "enable_sentinel_rate_limiter": false,
    "allow_master_keys": false,
    "policies": {
        "policy_source": "service",
        "policy_connection_string": "http://tyk_dashboard:3000",
        "policy_record_name": "tyk_policies"
    },
    "hash_keys": true,
    "close_connections": true,
    "allow_insecure_configs": true,
     "coprocess_options": {
        "enable_coprocess": false,
        "coprocess_grpc_server": ""
    },
    "enable_bundle_downloader": true,
    "bundle_base_url": "",
    "global_session_lifetime": 100,
    "force_global_session_lifetime": false,
    "max_idle_connections_per_host": 100
}

And this is my API spec (exported from the dashboard):

{
    "id": "5b168c8052b69d00016fc3fc",
    "name": "Core",
    "slug": "core",
    "api_id": "597e8d9eb90e4b886b1535acb42bbabd",
    "org_id": "5b168bb3b350f600012073d1",
    "use_keyless": false,
    "use_oauth2": true,
    "use_openid": false,
    "openid_options": {
        "providers": [],
        "segregate_by_client": false
    },
    "oauth_meta": {
        "allowed_access_types": [
            "authorization_code",
            "refresh_token",
            "password",
            "client_credentials"
        ],
        "allowed_authorize_types": [
            "token",
            "code"
        ],
        "auth_login_redirect": "http://login.dev.zetkin.org/login"
    },
    "auth": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false
    },
    "use_basic_auth": false,
    "use_mutual_tls_auth": false,
    "client_certificates": [],
    "upstream_certificates": {},
    "pinned_public_keys": {},
    "enable_jwt": false,
    "use_standard_auth": false,
    "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": "url",
        "key": "x-api-version"
    },
    "version_data": {
        "not_versioned": true,
        "default_version": "",
        "versions": {
            "1": {
                "name": "1",
                "expires": "",
                "paths": {
                    "ignored": [],
                    "white_list": [],
                    "black_list": []
                },
                "use_extended_paths": true,
                "extended_paths": {
                    "ignored": [
                        {
                            "path": "/orgs/{oid}/people/{pid}/avatar",
                            "method_actions": {
                                "GET": {
                                    "action": "no_action",
                                    "code": 200,
                                    "data": "",
                                    "headers": {}
                                }
                            }
                        },
                        {
                            "path": "/users/{id}/avatar",
                            "method_actions": {
                                "GET": {
                                    "action": "no_action",
                                    "code": 200,
                                    "data": "",
                                    "headers": {}
                                }
                            }
                        },
                        {
                            "path": "/orgs/{id}/avatar",
                            "method_actions": {
                                "GET": {
                                    "action": "no_action",
                                    "code": 200,
                                    "data": "",
                                    "headers": {}
                                }
                            }
                        },
                        {
                            "path": "/orgs/{id}",
                            "method_actions": {
                                "GET": {
                                    "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": "/",
        "target_url": "http://zetkincore:8080",
        "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": "",
            "port_data_path": "",
            "target_path": "",
            "use_target_list": false,
            "cache_timeout": 0,
            "endpoint_returns_list": false
        },
        "transport": {
            "ssl_ciphers": [],
            "ssl_min_version": 0,
            "proxy_url": ""
        }
    },
    "disable_rate_limit": true,
    "disable_quota": true,
    "custom_middleware": {
        "pre": [],
        "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": 40,
        "enable_cache": true,
        "cache_all_safe_requests": false,
        "cache_response_codes": [],
        "enable_upstream_cache_control": false,
        "cache_control_ttl_header": ""
    },
    "session_lifetime": 0,
    "active": true,
    "auth_provider": {
        "name": "",
        "storage_engine": "",
        "meta": {}
    },
    "session_provider": {
        "name": "",
        "storage_engine": "",
        "meta": {}
    },
    "event_handlers": {
        "events": {}
    },
    "enable_batch_request_support": false,
    "enable_ip_whitelisting": false,
    "allowed_ips": [],
    "enable_ip_blacklisting": false,
    "blacklisted_ips": [],
    "dont_set_quota_on_create": false,
    "expire_analytics_after": 0,
    "response_processors": [],
    "CORS": {
        "enable": true,
        "allowed_origins": [
            "*.dev.zetkin.org"
        ],
        "allowed_methods": [
            "PATCH",
            "PUT",
            "GET",
            "POST",
            "DELETE"
        ],
        "allowed_headers": [
            "Authorization",
            "Accept",
            "Content-Type"
        ],
        "exposed_headers": [],
        "allow_credentials": true,
        "max_age": 24,
        "options_passthrough": false,
        "debug": false
    },
    "domain": "api.dev.zetkin.org",
    "do_not_track": false,
    "tags": [],
    "enable_context_vars": false,
    "config_data": {},
    "tag_headers": [],
    "global_rate_limit": {
        "rate": 0,
        "per": 0
    },
    "strip_auth_data": false
}

Let me know if you find anything odd with these. Thank you so much for helping out!

Any ideas based on my configuration, @leon? :slight_smile:

I have figured it out now. The error seems to only appear when my listen_path is "/". If I add some sort of prefix, e.g. "/core/", and make the necessary changes everywhere, it works.

I tried making my authorization request to http://tyk_gateway:80//tyk/oauth/authorize-client/ (note the extra slash prefixing the path) but that was redirected back to the original URL without the extra slash. That makes sense, but it seems there is no way of reaching the Tyk/OAuth endpoints for an API which listens on /.

Could this be a bug?

It definitely looks like a bug!

Can you fill it on https://github.com/TykTechnologies/tyk ?

Thank you.

I have created a bug report now, at https://github.com/TykTechnologies/tyk/issues/1780