Tyk OAS URL rewrite trigger - JWT claim context variables empty for non-string/nested claims?

Running Tyk Gateway v5.11 in OAS mode. We’re trying to enforce a per-operation JWT claim check using URL rewrite trigger requestContextMatches, but we’re hitting what appears to be a hard limitation: context variables for JWT claims (jwt_claims_) are only populated for root-level string properties on the token. Any claim that is an object, array, or nested property appears to be empty/null in the request context.

Our JWT structure (simplified):

{
  "iss": "https://example.cloudflareaccess.com",
  "sub": "...",
  "custom": {
    "omig_api_roles": "media:read"
  }
}

jwt_claims_custom is empty at trigger evaluation time - Tyk does not appear to serialize the object or flatten its properties into child context variables.

What we’ve tried:

  • jwt_claims_custom → empty (object claim)
  • jwt_claims_custom.omig_api_roles → not a valid context variable name
  • jwt_claims_omig_api_roles → empty (not a root-level claim)

Stripped-down API definition:

Stripped-down API definition:
{
    "openapi": "3.0.3",
    "info": {
        "title": "Media API - Retrieve recipient-based and file-based media files",
        "version": "1.0.0"
    },
    "servers": [
        {
            "url": "http://testapi01.local:8080"
        }
    ],
    "paths": {
        "/v1/file/{fileKey}/recips/{recipient}": {
            "get": {
                "operationId": "getRecipentFile",
                "parameters": [
                    {
                        "name": "fileKey",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "recipient",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Retrieved"
                    },
                    "401": {
                        "description": "Unauthorized"
                    },
                    "403": {
                        "description": "Forbidden"
                    }
                },
                "x-tyk-api-gateway": {
                    "middleware": {}
                }
            }
        },
        "/v1/file/{fileKey}": {
            "get": {
                "operationId": "getFile",
                "parameters": [
                    {
                        "name": "fileKey",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Retrieved"
                    },
                    "401": {
                        "description": "Unauthorized"
                    },
                    "403": {
                        "description": "Forbidden"
                    }
                },
                "x-tyk-api-gateway": {
                    "middleware": {}
                }
            }
        },
        "/internal/forbidden": {
            "get": {
                "operationId": "forbidden",
                "responses": {
                    "403": {
                        "description": "Forbidden"
                    }
                },
                "x-tyk-api-gateway": {
                    "middleware": {}
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "auth0Jwt": {
                "type": "http",
                "scheme": "bearer",
                "bearerFormat": "JWT"
            }
        }
    },
    "security": [
        {
            "auth0Jwt": []
        }
    ],
    "x-tyk-api-gateway": {
        "info": {
            "id": "media-api-dev",
            "name": "Media API Dev",
            "state": {
                "active": true
            }
        },
        "server": {
            "listenPath": {
                "value": "/media-dev/api",
                "strip": true
            },
            "authentication": {
                "enabled": true,
                "securitySchemes": {
                    "auth0Jwt": {
                        "enabled": true,
                        "defaultPolicies": [
                            "auth0-default"
                        ],
                        "header": {
                            "enabled": true,
                            "name": "Authorization"
                        },
                        "cookie": {
                            "enabled": true,
                            "name": "CF_Authorization"
                        },
                        "jwksURIs": [
                            {
                                "url": "https://jwksurl01/jwks.json"
                            },
                            {
                                "url": "https://jwksurl02/certs"
                            }
                        ],
                        "allowedIssuers": [
                            "https://issuer01/",
                            "https://issuer02/"
                        ],
                        "subjectClaims": [
                            "sub"
                        ],
                        "allowedAudiences": [
                            "https://aud01",
                            "https://aud02",
                            "https://aud03"
                        ],
                        "signingMethod": "rsa",
                        "jtiValidation": {
                            "enabled": false
                        }
                    }
                }
            }
        },
        "upstream": {
            "url": "http://legacy-upstream"
        },
        "middleware": {
            "global": {
                "contextVariables": {
                    "enabled": true
                },
                "isOAS": true,
                "transformRequestHeaders": {
                    "enabled": true,
                    "add": [
                        {
                            "name": "Authorization",
                            "value": "Basic secrets://api_dev_upstream_basic_creds"
                        }
                    ],
                    "remove": []
                },
                "cache": {
                    "enabled": true
                }
            },
            "operations": {
                "getRecipentFile": {
                    "urlRewrite": {
                        "enabled": true,
                        "pattern": "/v1/file/(.*)/recips/(.*)",
                        "rewriteTo": "/mm-company-webservice/rest/reps/companyDap/docs/$1/recips/$2",
                        "triggers": [
                            {
                                "condition": "any",
                                "rewriteTo": "tyk://self/internal/forbidden",
                                "rules": [
                                    {
                                        "in": "requestContext",
                                        "name": "jwt_claims_custom",
                                        "pattern": "\"company_api_roles\":\"[^\"]*media:read",
                                        "negate": true
                                    }
                                ]
                            }
                        ]
                    }
                },
                "getFile": {
                    "urlRewrite": {
                        "enabled": true,
                        "pattern": "/v1/file/(.*)",
                        "rewriteTo": "/mm-company-webservice/rest/reps/companyDev/docs/$1/file",
                        "triggers": [
                            {
                                "condition": "any",
                                "rewriteTo": "tyk://self/internal/forbidden",
                                "rules": [
                                    {
                                        "in": "requestContext",
                                        "name": "jwt_claims_custom",
                                        "pattern": "\"company_api_roles\":\"[^\"]*media:read",
                                        "negate": true
                                    }
                                ]
                            }
                        ]
                    }
                },
                "forbidden": {
                    "internal": {
                        "enabled": true
                    },
                    "mockResponse": {
                        "enabled": true,
                        "code": 403,
                        "body": "{\"error\": \"missing required claim\"}"
                    }
                }
            }
        }
    }
}

Questions:

  1. Is this a confirmed limitation - that requestContextMatches in URL rewrite triggers can only match root-level string JWT claims?

  2. Is there any mechanism in Tyk OAS v5.x to access nested or object-type claim properties in trigger rules?

  3. Is there an alternative approach for per-operation JWT claim enforcement in OAS that doesn’t require a Go plugin? (customClaimValidation appears to be API-wide only.)

Trying to determine whether this is a configuration gap on our end or an actual platform limitation before escalating.