Update Key - Success message without any updates

We are trying to update a Key at Tyk, actually, we are just extending the “expires” field, to allow the key to be renewed.

Below is the update to update the key:

2023-08-23T22:22:14+0000 https://<AWS_LB_ADDRESS>:443 "GET /tyk/keys/eyJvcmciOiIxIiwiaWQiOiJkMTM4OGQ2Zjg5Yzg0NzAwOTA4NTRjNzU3ODdjZmU0NSIsImgiOiJtdXJtdXIxMjgifQ== HTTP/1.1" 200 1888
{
  "last_check": 0,
  "allowance": 1000,
  "rate": 1000,
  "per": 1,
  "throttle_interval": 0,
  "throttle_retry_limit": 0,
  "max_query_depth": 0,
  "date_created": "2023-08-23T18:50:05.361952176Z",
  "expires": 1708368604,
  "quota_max": -1,
  "quota_renews": 1692816665,
  "quota_remaining": -1,
  "quota_renewal_rate": 60,
  "access_rights": {
    "graphql": {
      "api_name": "graphql",
      "api_id": "graphql",
      "versions": [
        "Default"
      ],
      "allowed_urls": [
        {
          "url": "/app/graphql(.*)$",
          "methods": [
            "GET",
            "POST",
            "PUT",
            "DELETE",
            "HEAD"
          ]
        }
      ],
      "restricted_types": null,
      "allowed_types": null,
      "limit": {
        "rate": 0,
        "per": 1,
        "throttle_interval": 0,
        "throttle_retry_limit": 0,
        "max_query_depth": 0,
        "quota_max": 3000,
        "quota_renews": 0,
        "quota_remaining": 3000,
        "quota_renewal_rate": 60
      },
      "field_access_rights": null,
      "disable_introspection": false,
      "allowance_scope": "graphql"
    },
    "tykws": {
      "api_name": "tykws",
      "api_id": "tykws",
      "versions": [
        "Default"
      ],
      "allowed_urls": [
        {
          "url": "/tykws/token/renew(.*)$",
          "methods": [
            "GET",
            "POST",
            "PUT",
            "DELETE",
            "HEAD"
          ]
        },
        {
          "url": "/tykws/token/refresh(.*)$",
          "methods": [
            "GET",
            "POST",
            "PUT",
            "DELETE",
            "HEAD"
          ]
        }
      ],
      "restricted_types": null,
      "allowed_types": null,
      "limit": {
        "rate": 0,
        "per": 1,
        "throttle_interval": 0,
        "throttle_retry_limit": 0,
        "max_query_depth": 0,
        "quota_max": 3000,
        "quota_renews": 1692829340,
        "quota_remaining": 2999,
        "quota_renewal_rate": 60
      },
      "field_access_rights": null,
      "disable_introspection": false,
      "allowance_scope": "tykws"
    }
  },
  "org_id": "1",
  "oauth_client_id": "",
  "oauth_keys": null,
  "certificate": "",
  "basic_auth_data": {
    "password": "",
    "hash_type": ""
  },
  "jwt_data": {
    "secret": ""
  },
  "hmac_enabled": false,
  "enable_http_signature_validation": false,
  "hmac_string": "",
  "rsa_certificate_id": "",
  "is_inactive": false,
  "apply_policy_id": "",
  "apply_policies": [
    "graphql",
    "tykws"
  ],
  "data_expires": 0,
  "monitor": {
    "trigger_limits": null
  },
  "enable_detail_recording": false,
  "enable_detailed_recording": false,
  "meta_data": {},
  "tags": [],
  "alias": "",
  "last_updated": "1692816605",
  "id_extractor_deadline": 0,
  "session_lifetime": 0
}
2023-08-23T22:22:14+0000 Starting new HTTPS connection (1): <AWS_LB_ADDRESS>:443
2023-08-23T22:22:14+0000 https://<AWS_LB_ADDRESS>:443 "PUT /tyk/keys/eyJvcmciOiIxIiwiaWQiOiJkMTM4OGQ2Zjg5Yzg0NzAwOTA4NTRjNzU3ODdjZmU0NSIsImgiOiJtdXJtdXIxMjgifQ== HTTP/1.1" 200 137
2023-08-23T22:22:14+0000 {"key":"eyJvcmciOiIxIiwiaWQiOiJkMTM4OGQ2Zjg5Yzg0NzAwOTA4NTRjNzU3ODdjZmU0NSIsImgiOiJtdXJtdXIxMjgifQ==","status":"ok","action":"modified"}

As we can see, the API was called with the PUT message, the JSON object is properly accepted and we get a success message.

However, when we go to the TYK GW API to retrieve the key information, the “expires” value is not updated.

Tyk Gateway Logs

time="Aug 23 22:22:14" level=info msg="Reset quota for key." inbound-key="****fQ==" key="quota-eyJvcmciOiIxIiwiaWQiOiJkMTM4OGQ2Zjg5Yzg0NzAwOTA4NTRjNzU3ODdjZmU0NSIsImgiOiJtdXJtdXIxMjgifQ==" prefix=auth-mgr
time="Aug 23 22:22:14" level=info msg="Reset quota for key." inbound-key="****fQ==" key="quota-eyJvcmciOiIxIiwiaWQiOiJkMTM4OGQ2Zjg5Yzg0NzAwOTA4NTRjNzU3ODdjZmU0NSIsImgiOiJtdXJtdXIxMjgifQ==" prefix=auth-mgr
time="Aug 23 22:22:14" level=info msg="Key added or updated." api_id=-- expires=1708368604 key="****fQ==" org_id=1 path=-- prefix=api server_name=system user_id=system user_ip=--
time="Aug 23 22:22:14" level=debug msg="EVENT FIRED: TokenUpdated"
time="Aug 23 22:22:14" level=debug msg=Finished api_id=tykws api_name=tykws mw=ReverseProxy ns=150448332 org_id=1
time="Aug 23 22:22:14" level=debug msg="Upstream request took (ms): 150.470274"

Did you call the hot reload API?

Each time a modification is made to the gateway the hot-reload API needs to be called for the latest changes to be retrieved.

Yes, this is being done.
I’ve build a small python utility/app that works either as a CLI or as a Rest Webservice. This allows me to create keys or make changes using both options on the daily basis tasks, just a helper script.

The CLI/RestApp works basically calling the Tyk Gateway APIs using Python and Requests module.

The weird thing is:

  • The CLI works and updates the “expires” value for a Key properly.

  • When I deploy my App and call it from the web service locally, it works too. (just like flask localhost:5000/myapp/refresh_token)

  • When the App is running on kubernetes and the POD or Service is called directly (forwarded), it works.

  • if I create an AWS Load Balancer and call my app, it updates the key properly with the correct “expires” value.

  • The problem only happens when I call the endpoint that is hosted on Tyk Gateway. Even the logs shows successful, but it doesn’t update.

Something like this:

GET - https://TYK_GW_HOST/myapp/refresh_token

Once you hit this app via Tyk Gateway, the “refresh_token” endpoint (a flask app), will call the https://TYK_GW_HOST/tyk/keys endpoint with a PUT operation and add additional 30 days in the expire date.

All logs shows properly success messages, even the “response” gets 200/Modified message.

My code pretty much gets Keys and Endpoints to call Tyk Gateway API and make the required changes:

url = f"keys/{kwargs['key_id']}"
response = self._request(method="put", url=url, payload=key_payload)
def _request(self, method=str, url=str, payload=None) -> object | None:
  if method == "GET":
      response = requests.get(url, headers=self.header, verify=False)
  elif method == "POST":
      response = requests.post(url, headers=self.header, data=json.dumps(payload, indent=2) , verify=False)
  elif method == "PUT":
      response = requests.put(url, headers=self.header, data=json.dumps(payload, indent=2), verify=False)
  elif method == "DELETE":
      response = requests.delete(url, headers=self.header, verify=False)
https://internal-tyk-gateway-2-<redacted>.us-east-1.elb.amazonaws.com:443 "PUT **/tyk/keys/eyJvcmciOiIxIiwiaWQiOiJjNjZjZTE1Y2UzZWI0MzY2OTUzZTAxNzUyYjFiZTAwYSIsImgiOiJtdXJtdXIxMjgifQ== HTTP/1.1" 200 137**
2023-08-24T16:49:20-0300 headers: {'x-tyk-authorization': '1234', 'Cache-Control': 'no-cache', 'Accept-Charset': 'UTF-8', 'x-tykc-key': '1234'}
2023-08-24T16:49:20-0300 Starting new HTTPS connection (1): internal-tyk-gateway-2-<redacted>.us-east-1.elb.amazonaws.com:443
2023-08-24T16:49:21-0300 https://internal-tyk-gateway-2-<redacted>.us-east-1.elb.amazonaws.com:443 "GET /tyk/reload/group HTTP/1.1" 200 29
2023-08-24T16:49:21-0300 <Response [200]>
2023-08-24T16:49:21-0300 Results:
 {'ret_code': 0, 'ret_message': {'key': 'eyJvcmciOiIxIiwiaWQiOiJjNjZjZTE1Y2UzZWI0MzY2OTUzZTAxNzUyYjFiZTAwYSIsImgiOiJtdXJtdXIxMjgifQ==', 'status': 'ok', 'action': 'modified'}}
2023-08-24T16:49:21-0300 127.0.0.1 - - [24/Aug/2023 16:49:21] "GET /token/renew HTTP/1.1" 200 -

What I’m trying to say is if I run my app in any way or kind of deployment, it’s working fine… except when I hit my application running behind tyk gateway.

ps: I’d be happy to demo my “small utility” working. :slight_smile:

btw, the endpoint and policy definition in tyk gateway is pretty simple:

{
    "name": "myapp",
    "slug": "myapp",
    "use_keyless": false,
    "use_basic_auth": false,
    "use_standard_auth": true,
    "api_id": "tykws",
    "org_id": "1",
    "version_data": {
      "not_versioned": true,
      "versions": {
        "Default": {
          "name": "Default",
          "use_extended_paths": true
        }
      }
    },
    "proxy": {
      "listen_path": "/myapp/",
      "target_url": "http://myapp.myapp.svc.cluster.local:8080/",
      "strip_listen_path": true,
      "transport": {
        "ssl_insecure_skip_verify": true
      }
    },
    "active": true
}
{
    "id": "myapp",
    "name": "myapp",
    "org_id": "1",
    "rate": 0,
    "per": 1,
    "quota_max": 3000,
    "quota_renewal_rate": 60,
    "throttle_interval": 0,
    "throttle_retry_limit": 0,
    "max_query_depth": 0,
    "access_rights": {
        "myapp": {
            "api_id": "myapp",
            "api_name": "myapp",
            "allowed_urls": [
                {
                    "url": "/myapp/token/renew(.*)$",
                    "methods": ["GET", "POST", "PUT", "DELETE", "HEAD"]
                },
                {
                    "url": "/myapp/token/refresh(.*)$",
                    "methods": ["GET", "POST", "PUT", "DELETE", "HEAD"]
                }
            ],
            "versions": ["Default"]
        }
    },
    "hmac_enabled": false,
    "enable_http_signature_validation": false,
    "active": false,
    "is_inactive": false,
    "tags": null,
    "key_expires_in": 0,
    "partitions": {
        "quota": false,
        "rate_limit": false,
        "complexity": false,
        "acl": false,
        "per_api": false
    },
    "last_updated": "",
    "meta_data": null,
    "graphql_access_rights": null
}

Thanks,
Daniel

The api_id in the policy.access_rights and from the api_definition don’t match

{
... 
  "use_standard_auth": true,
    "api_id": "tykws",
    "org_id": "1",
...

If you are still getting the issue then I did notice the key you shared earlier has 2 policies graphql and tykws. Maybe the expires field is picked up from one of the keys but I’d have to test and confirm that

Hi Olu,

Sorry, that was a mistake. Before submitting tickets here I usually replace some of the texts to either remove any company information or to make it easier to follow.

Right now, this is my “latest” findings.

If I hit my endpoint http://<aws_alb>/myapp/token/renew (GET)
→ It doesn’t work. Even though, the Tyk GW API returns the proper message saying the key was updated, I can see the json output that is passed to the Tyk GW API, looks correct. Even if I save the .json output and then call Tyk GW manually to update the key, it works.

However, if I simply make a “incorrect” call like http://<aws_alb>/myapp/token/renew123 and then hit the previous endpoint again, then the key is updated.

I also added the parameter TYK_GW_LOCALSESSIONCACHE_DISABLECACHESESSIONSTATE and re-deployed Tyk, no luck.

I’ll try to prepare a very simple POC in hope I can simulate the problem and you can validate at your side. Give me 1 or 2 days please, if possible.

Hi @Olu ,

Ok, I got a working demo that can be replicated by anyone.
If you have time and want to replicate the “problem/behavior”, I’m pasting the steps below.
If you think posting in github page as a bug would be better, let me know please.

We’ll build a Flask/Python app hosting the following endpoint/API:
GET - <TYK_GW_ENDPOINT>/myapp/token/renew

This requires two headers, one to authenticate in the Tyk endpoint and another one to identify the key that is calling the API.

Authorization: ‘Bearer <token>’
x-tykc-key: ‘<token>’

We will run two tests:
1- Running the App locally and calling the Flask API, directly from your computer, which will call tyk gateway as per the code. This will work all the times.
2- Calling the same Flask API hosted in a Kubernetes cluster (where Tyk GW is installed). This only works under a certain condition to be met.

On the second test, there are two cenarios:
1- When you hit the API for the first time with the proper settings (/myapp/token/renew), it will show the success message, but the key will not be updated.
2- Then, we’ll fake a wrong api call like /myapp/token/renew123 (the page will fail!)
3- You’ll finally hit the correct endpoint just like in step .1 , you’ll notice that the key will be updated successfully.

If you hit the correct endpoint again, it doesn’t work. But if you fake an incorrect one like /myapp/token/renew123 and try again, it will work.
Also, in every attempt, the return message shows as “modified”

To test locally:

Clone the repository

git clone https://github.com/dszortyka/poc-tyk-cli
cd poc-tyk-cli

Run pipenv to build minimum packages for the application

pipenv install --python 3.9
pipenv shell

define variables

declare -x TYK_API_KEY=<tyk api key to manage tyk gw>
declare -x TYK_GATEWAY_ENV=<the tyk gateway host only, without tyk endpoint)

run the application locally and pay attention to the logs. They are the same ones to when running from a Kubernetes POD.

python3 myapp.py

hit the application endpoint using insomnia or postman or curl

curl..

check the logs and ensure the key was updated using Tyk GW APIs.

URL: <TYK_GATEWAY_ENDPOINT>/tyk/keys/eyJvcmciOiIxIiwiaWQiOiJiZWMxNWEzNjJmNmI0NWZiYWE3Y2FjZjEyYmRmYzE5OCIsImgiOiJtdXJtdXIxMjgifQ==
Response: <Response [200]>
Key Retrieved from Tyk GW:
{'last_check': 0, 'allowance': 1000, 'rate': 0, 'per': 1, 'throttle_interval': 0, 'throttle_retry_limit': 0, 'max_query_depth': 0, 'date_created': '2023-08-28T15:59:24.727409646Z', 'expires': 1701014366, 'quota_max': 3000, 'quota_renews': 1693239067, 'quota_remaining': 2999, 'quota_renewal_rate': 60, 'access_rights': {'myapp': {'api_name': 'myapp', 'api_id': 'myapp', 'versions': ['Default'], 'allowed_urls': [{'url': '/myapp/token/renew(.*)$', 'methods': ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']}, {'url': '/myapp/token/refresh(.*)$', 'methods': ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']}], 'restricted_types': None, 'allowed_types': None, 'limit': {'rate': 0, 'per': 1, 'throttle_interval': 0, 'throttle_retry_limit': 0, 'max_query_depth': 0, 'quota_max': 3000, 'quota_renews': 1693239067, 'quota_remaining': 2999, 'quota_renewal_rate': 60}, 'field_access_rights': None, 'disable_introspection': False, 'allowance_scope': ''}}, 'org_id': '1', 'oauth_client_id': '', 'oauth_keys': None, 'certificate': '', 'basic_auth_data': {'password': '', 'hash_type': ''}, 'jwt_data': {'secret': ''}, 'hmac_enabled': False, 'enable_http_signature_validation': False, 'hmac_string': '', 'rsa_certificate_id': '', 'is_inactive': False, 'apply_policy_id': '', 'apply_policies': ['myapp'], 'data_expires': 0, 'monitor': {'trigger_limits': None}, 'enable_detail_recording': False, 'enable_detailed_recording': False, 'meta_data': {}, 'tags': [], 'alias': 'myapp', 'last_updated': '1693238627', 'id_extractor_deadline': 0, 'session_lifetime': 0}
Current value for Expires: 1701014366
New value for expires: 1701014367
New Payload
{'last_check': 0, 'allowance': 1000, 'rate': 0, 'per': 1, 'throttle_interval': 0, 'throttle_retry_limit': 0, 'max_query_depth': 0, 'date_created': '2023-08-28T15:59:24.727409646Z', 'expires': 1701014367, 'quota_max': 3000, 'quota_renews': 1693239067, 'quota_remaining': 2999, 'quota_renewal_rate': 60, 'access_rights': {'myapp': {'api_name': 'myapp', 'api_id': 'myapp', 'versions': ['Default'], 'allowed_urls': [{'url': '/myapp/token/renew(.*)$', 'methods': ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']}, {'url': '/myapp/token/refresh(.*)$', 'methods': ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']}], 'restricted_types': None, 'allowed_types': None, 'limit': {'rate': 0, 'per': 1, 'throttle_interval': 0, 'throttle_retry_limit': 0, 'max_query_depth': 0, 'quota_max': 3000, 'quota_renews': 1693239067, 'quota_remaining': 2999, 'quota_renewal_rate': 60}, 'field_access_rights': None, 'disable_introspection': False, 'allowance_scope': ''}}, 'org_id': '1', 'oauth_client_id': '', 'oauth_keys': None, 'certificate': '', 'basic_auth_data': {'password': '', 'hash_type': ''}, 'jwt_data': {'secret': ''}, 'hmac_enabled': False, 'enable_http_signature_validation': False, 'hmac_string': '', 'rsa_certificate_id': '', 'is_inactive': False, 'apply_policy_id': '', 'apply_policies': ['myapp'], 'data_expires': 0, 'monitor': {'trigger_limits': None}, 'enable_detail_recording': False, 'enable_detailed_recording': False, 'meta_data': {}, 'tags': [], 'alias': 'myapp', 'last_updated': '1693238627', 'id_extractor_deadline': 0, 'session_lifetime': 0}
Response from Update command:
{"key":"eyJvcmciOiIxIiwiaWQiOiJiZWMxNWEzNjJmNmI0NWZiYWE3Y2FjZjEyYmRmYzE5OCIsImgiOiJtdXJtdXIxMjgifQ==","status":"ok","action":"modified"}

To test it in a Kubernetes cluster
Build the image

docker build --no-cache --platform linux/amd64 --build-arg http_proxy \
    --build-arg https_proxy --build-arg  --build-arg GIT_COMMIT=$(git rev-parse HEAD) \
    -t <YOUR_ARTIFACTORY_REPOSITORY_OF_CHOICE>myapp:dev -f Dockerfile .

Deploy it in a kubernetes cluster where Tyk Gateway is running

kubectl create ns myapp
kubectl config set-context --current --namespace=myapp
kubectl apply -f deploy-k8s.yaml

Deploy the API and the Policy, Using the Swagger API List:

Assign the Policy to an existing key or create a new Key with the policy assigned to it.

Go into the POD and start the python application


# get pod name
kubectl get pods|grep myapp

# open bash 
kubectl exec -it myapp-767c8bc686-7h7fn -- bash

# run the app
python3 myapp.py

From this point, Tyk Gateway has the API definition and will be able to proxy the request because the “myapp” service is up and running.

  • Open your Insomnia/Postman or Curl and hit the Tyk Gateway endpoint for MyApp.
    Check the logs
    Notice that the logs shows the key was updated properly, even when it was not.
    Go back and check the key (expires) value, it’s not updated.

  • Then, try to modify the endpoint to /myapp/token/renew123 . The request will fail, ok.
    Go back and adjust to the correct endpoint /myapp/token/renew , only then the key will be updated.
    And if you try to hit the same correct endpoint more than once, it won’t work. It’s like you always have to “clean up” and try again.

  • Below message is always triggered, but only works when I hit first /myapp/token/renew123 and then hit the correct one /myapp/token/renew

time="Aug 28 16:26:42" level=info msg="Reset quota for key." inbound-key="****fQ==" key="quota-eyJvcmciOiIxIiwiaWQiOiJiZWMxNWEzNjJmNmI0NWZiYWE3Y2FjZjEyYmRmYzE5OCIsImgiOiJtdXJtdXIxMjgifQ==" prefix=auth-mgr
time="Aug 28 16:26:42" level=info msg="Key added or updated." api_id=-- expires=1701014367 key="****fQ==" org_id=1 path=-- prefix=api server_name=system user_id=system user_ip=--
time="Aug 28 16:26:42" level=debug msg="EVENT FIRED: TokenUpdated"
time="Aug 28 16:26:42" level=debug msg=Finished api_id=myapp api_name=myapp mw=ReverseProxy ns=95812551 org_id=1

- Kubernetes POD Logs:

root@myapp-767c8bc686-7h7fn:/mnt/app# python3 myapp.py
 * Serving Flask app 'myapp'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://100.64.17.202:5000
Press CTRL+C to quit
URL: https://<AWS_LOAD_BALANCER>.us-east-1.elb.amazonaws.com/tyk/keys/eyJvcmciOiIxIiwiaWQiOiJiZWMxNWEzNjJmNmI0NWZiYWE3Y2FjZjEyYmRmYzE5OCIsImgiOiJtdXJtdXIxMjgifQ==
Response: <Response [200]>
Key Retrieved from Tyk GW:
{'last_check': 0, 'allowance': 1000, 'rate': 0, 'per': 1, 'throttle_interval': 0, 'throttle_retry_limit': 0, 'max_query_depth': 0, 'date_created': '2023-08-28T15:59:24.727409646Z', 'expires': 1701014367, 'quota_max': 3000, 'quota_renews': 1693246538, 'quota_remaining': 2999, 'quota_renewal_rate': 60, 'access_rights': {'myapp': {'api_name': 'myapp', 'api_id': 'myapp', 'versions': ['Default'], 'allowed_urls': [{'url': '/myapp/token/renew(.*)$', 'methods': ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']}, {'url': '/myapp/token/refresh(.*)$', 'methods': ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']}], 'restricted_types': None, 'allowed_types': None, 'limit': {'rate': 0, 'per': 1, 'throttle_interval': 0, 'throttle_retry_limit': 0, 'max_query_depth': 0, 'quota_max': 3000, 'quota_renews': 1693246538, 'quota_remaining': 2999, 'quota_renewal_rate': 60}, 'field_access_rights': None, 'disable_introspection': False, 'allowance_scope': ''}}, 'org_id': '1', 'oauth_client_id': '', 'oauth_keys': None, 'certificate': '', 'basic_auth_data': {'password': '', 'hash_type': ''}, 'jwt_data': {'secret': ''}, 'hmac_enabled': False, 'enable_http_signature_validation': False, 'hmac_string': '', 'rsa_certificate_id': '', 'is_inactive': False, 'apply_policy_id': '', 'apply_policies': ['myapp'], 'data_expires': 0, 'monitor': {'trigger_limits': None}, 'enable_detail_recording': False, 'enable_detailed_recording': False, 'meta_data': {}, 'tags': [], 'alias': 'myapp', 'last_updated': '1693240002', 'id_extractor_deadline': 0, 'session_lifetime': 0}
Current value for Expires: 1701014367
New value for expires: 1701014368
New Payload
{'last_check': 0, 'allowance': 1000, 'rate': 0, 'per': 1, 'throttle_interval': 0, 'throttle_retry_limit': 0, 'max_query_depth': 0, 'date_created': '2023-08-28T15:59:24.727409646Z', 'expires': 1701014368, 'quota_max': 3000, 'quota_renews': 1693246538, 'quota_remaining': 2999, 'quota_renewal_rate': 60, 'access_rights': {'myapp': {'api_name': 'myapp', 'api_id': 'myapp', 'versions': ['Default'], 'allowed_urls': [{'url': '/myapp/token/renew(.*)$', 'methods': ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']}, {'url': '/myapp/token/refresh(.*)$', 'methods': ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']}], 'restricted_types': None, 'allowed_types': None, 'limit': {'rate': 0, 'per': 1, 'throttle_interval': 0, 'throttle_retry_limit': 0, 'max_query_depth': 0, 'quota_max': 3000, 'quota_renews': 1693246538, 'quota_remaining': 2999, 'quota_renewal_rate': 60}, 'field_access_rights': None, 'disable_introspection': False, 'allowance_scope': ''}}, 'org_id': '1', 'oauth_client_id': '', 'oauth_keys': None, 'certificate': '', 'basic_auth_data': {'password': '', 'hash_type': ''}, 'jwt_data': {'secret': ''}, 'hmac_enabled': False, 'enable_http_signature_validation': False, 'hmac_string': '', 'rsa_certificate_id': '', 'is_inactive': False, 'apply_policy_id': '', 'apply_policies': ['myapp'], 'data_expires': 0, 'monitor': {'trigger_limits': None}, 'enable_detail_recording': False, 'enable_detailed_recording': False, 'meta_data': {}, 'tags': [], 'alias': 'myapp', 'last_updated': '1693240002', 'id_extractor_deadline': 0, 'session_lifetime': 0}

Response from Update command:
{"key":"eyJvcmciOiIxIiwiaWQiOiJiZWMxNWEzNjJmNmI0NWZiYWE3Y2FjZjEyYmRmYzE5OCIsImgiOiJtdXJtdXIxMjgifQ==","status":"ok","action":"modified"}

100.64.21.160 - - [28/Aug/2023 18:15:59] "GET /token/renew HTTP/1.1" 200 -


Response: <Response [200]>
Key Retrieved from Tyk GW:
{'last_check': 0, 'allowance': 1000, 'rate': 0, 'per': 1, 'throttle_interval': 0, 'throttle_retry_limit': 0, 'max_query_depth': 0, 'date_created': '2023-08-28T15:59:24.727409646Z', 'expires': 1701014367, 'quota_max': 3000, 'quota_renews': 1693246760, 'quota_remaining': 2999, 'quota_renewal_rate': 60, 'access_rights': {'myapp': {'api_name': 'myapp', 'api_id': 'myapp', 'versions': ['Default'], 'allowed_urls': [{'url': '/myapp/token/renew(.*)$', 'methods': ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']}, {'url': '/myapp/token/refresh(.*)$', 'methods': ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']}], 'restricted_types': None, 'allowed_types': None, 'limit': {'rate': 0, 'per': 1, 'throttle_interval': 0, 'throttle_retry_limit': 0, 'max_query_depth': 0, 'quota_max': 3000, 'quota_renews': 1693246760, 'quota_remaining': 2999, 'quota_renewal_rate': 60}, 'field_access_rights': None, 'disable_introspection': False, 'allowance_scope': ''}}, 'org_id': '1', 'oauth_client_id': '', 'oauth_keys': None, 'certificate': '', 'basic_auth_data': {'password': '', 'hash_type': ''}, 'jwt_data': {'secret': ''}, 'hmac_enabled': False, 'enable_http_signature_validation': False, 'hmac_string': '', 'rsa_certificate_id': '', 'is_inactive': False, 'apply_policy_id': '', 'apply_policies': ['myapp'], 'data_expires': 0, 'monitor': {'trigger_limits': None}, 'enable_detail_recording': False, 'enable_detailed_recording': False, 'meta_data': {}, 'tags': [], 'alias': 'myapp', 'last_updated': '1693240002', 'id_extractor_deadline': 0, 'session_lifetime': 0}

Current value for Expires: 1701014367
New value for expires: 1701014368
New Payload

{'last_check': 0, 'allowance': 1000, 'rate': 0, 'per': 1, 'throttle_interval': 0, 'throttle_retry_limit': 0, 'max_query_depth': 0, 'date_created': '2023-08-28T15:59:24.727409646Z', 'expires': 1701014368, 'quota_max': 3000, 'quota_renews': 1693246760, 'quota_remaining': 2999, 'quota_renewal_rate': 60, 'access_rights': {'myapp': {'api_name': 'myapp', 'api_id': 'myapp', 'versions': ['Default'], 'allowed_urls': [{'url': '/myapp/token/renew(.*)$', 'methods': ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']}, {'url': '/myapp/token/refresh(.*)$', 'methods': ['GET', 'POST', 'PUT', 'DELETE', 'HEAD']}], 'restricted_types': None, 'allowed_types': None, 'limit': {'rate': 0, 'per': 1, 'throttle_interval': 0, 'throttle_retry_limit': 0, 'max_query_depth': 0, 'quota_max': 3000, 'quota_renews': 1693246760, 'quota_remaining': 2999, 'quota_renewal_rate': 60}, 'field_access_rights': None, 'disable_introspection': False, 'allowance_scope': ''}}, 'org_id': '1', 'oauth_client_id': '', 'oauth_keys': None, 'certificate': '', 'basic_auth_data': {'password': '', 'hash_type': ''}, 'jwt_data': {'secret': ''}, 'hmac_enabled': False, 'enable_http_signature_validation': False, 'hmac_string': '', 'rsa_certificate_id': '', 'is_inactive': False, 'apply_policy_id': '', 'apply_policies': ['myapp'], 'data_expires': 0, 'monitor': {'trigger_limits': None}, 'enable_detail_recording': False, 'enable_detailed_recording': False, 'meta_data': {}, 'tags': [], 'alias': 'myapp', 'last_updated': '1693240002', 'id_extractor_deadline': 0, 'session_lifetime': 0}

Response from Update command:
{"key":"eyJvcmciOiIxIiwiaWQiOiJiZWMxNWEzNjJmNmI0NWZiYWE3Y2FjZjEyYmRmYzE5OCIsImgiOiJtdXJtdXIxMjgifQ==","status":"ok","action":"modified"}

Hit #1: → doesn’t work

Hit #2: → force wrong api

Hit #3 → same api, then it works

@dszortyka Will check this out but it might take some time

@dszortyka I reproduced the issue with the local test.

Just to confirm, what value do you set the expires field to?

I ask this because I had issues setting it to an expired value. The value takes an unix timestamp but it seems the value cannot be updated if the value supplied is less than the current/live timestamp. I checked the source code and it confirms my tests

Also, could verify the expires field has been updated from the expires field in the logs? I observed that the value of the expires field key corresponds to the output of the log when the key is recently updated

level=info msg="Key added or updated." api_id=-- expires=1701014368 key="****fQ==" org_id=default path=-- prefix=api server_name=system user_id=system user_ip=--

The key definition’s last_updated field also informs you when the key was last updated, so you can verify that the key was indeed updated.