Thanks, I got is working now, finally! But for other people reading this: These are the issues I stumbled upon, mixed with some questions:
-
I wondered for a long time why my JS-pre-middleware wasn’t loaded by Tyk. I expected the attribute custom_middleware.pre[].path
inside my /apps/api.json
to be relative to the path configured in middleware_path
in my tyk.conf
. This is not the case. The configured middleware_path
is only used for plugin-bundles (and maybe for other middleware drivers than JSVM). Real complicated stuff! Better use absolute paths in your api configuration!
-
Even better alternative to the previous paragraph: Only configure the middleware_path
inside your tyk.conf
and don’t touch your api-conf at all! Then place your JS-plugins into [middleware_path]/[api-id]/pre/
(for pre-plugins, in my case /etc/tyk/middleware/7ca7dc85-eee5-4dda-ba4e-f9b7a71f2336/pre/generateKeyMiddleware.js
). These plugins will automatically picked up by Tyk without defining them inside your api configuration. When doing it this way, the function inside your js-file needs to be named exactly like the js-file, sans the “.js”-suffix. I don’t know if this mechanism is documented anywhere; I found out about this by looking at the code. This took a while.
-
Don’t forget to set "enable_jsvm": true
in your tyk.conf!
-
This took me a loooong time to debug: When accessing request.Headers[]
from your plugin, keep in mind that the header names are transformed to camel case. In my case, OIDC_CLAIM_sub
has been transformed to Oidc_claim_sub
.
-
If your JS-files contain syntax errors or throw exceptions, Tyk won’t help you. Prepare to see the message Failed to decode middleware request data on return from VM: invalid character 'u' looking for beginning of value
.
-
Question: Why do I need to define the access_rights
for the session when calling TykSetKeyData()
when the session-object also contains apply_policy_id
? I think it’s redundant to have the access_rights defined inside the policy while being forced to also define them in the session-object created by the pre-plugin.
-
Bonus question: Why do I have to state the api_id both as the name of the object inside the access_rights
-object, and then again for the api_id
attribute of this very object? Can there be a use-case where the name of the object differs from the api_id specified inside the object?
For completion, here are my configs and plugin source:
/opt/tyk-gateway/tyk.conf:
{
"listen_address": "",
"listen_port": 8090,
"secret": "IT'S A SECRET TO EVERYBODY",
"template_path": "/opt/tyk-gateway/templates",
"tyk_js_path": "/opt/tyk-gateway/js/tyk.js",
"use_db_app_configs": false,
"app_path": "/etc/tyk/apps",
"middleware_path": "/etc/tyk/middleware",
"storage": {
"type": "redis",
"host": "localhost",
"port": 6379,
"username": "",
"password": "",
"database": 0,
"optimisation_max_idle": 500
},
"enable_jsvm": true,
"enable_analytics": true,
"health_check": {
"enable_health_checks": true,
"health_check_value_timeouts": 60
},
"optimisations_use_async_session_write": true,
"allow_master_keys": false,
"policies": {
"policy_source": "file",
"policy_record_name": "/etc/tyk/policies.json"
},
"hash_keys": false,
"suppress_redis_signal_reload": false
}
/etc/tyl/apps/api.json:
{
"name": "my-api",
"api_id": "7ca7dc85-eee5-4dda-ba4e-f9b7a71f2336",
"enable_context_vars": false,
"auth": {
"auth_header_name": "Oidc_claim_sub"
},
"version_data": {
"not_versioned": true,
"versions": {
"Default": {
"use_extended_paths": true,
"name": "Default"
}
}
},
"proxy": {
"listen_path": "/",
"target_url": "http://localhost:8080/"
},
"active": true
}
/etc/tyk/middleware/7ca7dc85-eee5-4dda-ba4e-f9b7a71f2336/pre/generateKeyMiddleware.js:
var generateKeyMiddleware = new TykJS.TykMiddleware.NewMiddleware({});
generateKeyMiddleware.NewProcessRequest(function(request, session) {
var token = request.Headers["Oidc_claim_sub"];
log("Token: " + token);
if (!token) {
request.ReturnOverrides.ResponseCode = 401;
request.ReturnOverrides.ResponseError = "missing token";
return generateKeyMiddleware.ReturnData(request, {});
}
var session = JSON.parse(TykGetKeyData(token));
if (session.status == "error") {
log("Session not found, creating new one");
session = {
"apply_policy_id": "vp_api",
"access_rights": {
"7ca7dc85-eee5-4dda-ba4e-f9b7a71f2336": {
"api_id": "7ca7dc85-eee5-4dda-ba4e-f9b7a71f2336",
"versions": [
"Default"
]
}
}
};
TykSetKeyData(token, JSON.stringify(session));
}
return generateKeyMiddleware.ReturnData(request, {});
});
// Ensure init with a post-declaration log message
log("Initializing generateKeyMiddleware");
I would love to omit the access_rights-object from the js-plugin…
Thank you for all your help this far!