Session.expires not being obeyed?

I am logging this in a custom JSVM middleware PRE hook

2017-07-24T21:55:00.697563103Z time=“Jul 24 21:55:00” level=info msg=“Pre-existing session exists… using, curr_epoch: 1500933301 session.expires: 1500933217” type=log-msg

So the session.expires value is < the current epoch. Why is this session never going away? I am retrieving it via

session = JSON.parse(TykGetKeyData(authorizationHeaderValue))

It won’t be deleted if that’s what you mean - Tyk does not set TTLs on session objects by default.

The session will be rejected by the token auth though because it is expired, but the object is not evicted because there is a difference between expiry and deletion.

If we delete the session, we can’t tell the user it has expired. And in some cases you may want to extend the session instead of replacing it (for example the token holder might not be able to renew the token because it is out of their control)

If you want a TTL for the key, you need to set the session_expires value in the API Definition evel to a sane default, then all created sessions will have this TTL added and be evicted after this period of seconds.

The session will be rejected by the token auth though because it is expired, but the object is not evicted because there is a difference between expiry and deletion.

With “by the token auth” do you mean it will be auto rejected if the following is implemented?

Meaning that if I set an “expires” epoch on the session object and then it via TykSetKeyData(authHash, JSON.stringify(session)); … on the next request following that “expires” being reached (using “auth tokens” per what you noted below) Tyk will return what exactly, on a call to session = JSON.parse(TykGetKeyData(authHash)).

Will session.status == "error"?

Also what does this mean in the logs when I call TykSetKeyData(authHash, JSON.stringify(session));

2017-07-26T14:14:36.171578836Z time="Jul 26 14:14:36" level=warning msg="Incorrect key expiry setting detected, correcting"

Actually what I’ve observed is if I set
“session.expires”, the session object is still returned against that key, with status = OK, but after my hook returns I get in the logs

2017-07-26T14:21:34.962742129Z time="Jul 26 14:21:34" level=error msg="request error: Key has expired, please renew" api_id=xxx org_id=xxx path="/" server_name="http://192.168.0.148:9080/service/xxx" user_id="****XXX=" user_ip=172.18.0.1

Implying that my middleware code must do the checking against the “session.expires” value and re-auth to my backend and then reset the “expires” to a new value… correct?

We are crossing into the territory covered by the conversation in this post.

The lookup is directly against redis, so it will always return data if it is in the DB. The function will not check expires, you would need to do that yourself or as per the suggestion in the other post, you let Tyk do it for you when you set an internal auth header.

You could do this, or you could let the auth middleware do it for you as mentioned above…

Confused.

So I have the internal auth header being set in my pre middleware, and “Auth Token” with “Auth Key Header Name” = “x-internal-authorization” configured for the API security. My pre middleware function is always called, and I am still having to manage the enforcement of the session.expires value.

What am I missing here? I don’t see tyk managing the enforcement of the session.expires value as you describe above.

What changes do I need to make here?

log("====> myAuth Auth initializing");

var myAuth = new TykJS.TykMiddleware.NewMiddleware({});

myAuth.NewProcessRequest(function(request, session, config) {

	var debugMode =	(config.config_data.debug_mode == 'true');

	if (debugMode) {
		log("----> Running myAuth JSVM Auth Middleware");
		log("config = " + JSON.stringify(config));
		log("request = " + JSON.stringify(request));
		log("session = " + JSON.stringify(session));
	}


	var rawAuthorization = request.Headers["Authorization"];

	if (rawAuthorization && rawAuthorization.length > 0) {
		rawAuthorization = rawAuthorization[0];

	} else {
		request.ReturnOverrides.ResponseCode = 401;
		request.ReturnOverrides.ResponseError = 'Authentication required';
		return myAuth.ReturnData(request, {});
	}

	var authHash = rawAuthorization; //todo hash

	request.SetHeaders = { "x-internal-authorization" : authHash };

	if (debugMode) {
		log("rawAuthorization = "+rawAuthorization);
		log("authHash = "+authHash);
	}


	var tykSession = JSON.parse(TykGetKeyData(authHash))

	if (debugMode) {
	    log("tykSession = " + JSON.stringify(tykSession));
	}

	var curr_epoch = Math.round(new Date().getTime() / 1000);

	if (tykSession.status == "error" || tykSession.expires <= curr_epoch) {

		if (debugMode) {
			log("session.status="+tykSession.status+" curr_epoch: " + curr_epoch + " session.expires: " + tykSession.expires +
				", attempting auth against: " + config.config_data.my_host +
				" as: "  + config.config_data.requesting_system +
				" for: " + config.config_data.requested_resource_tag);
		}

		var newRequest = {
				"Method": "GET",
				"Body": "",
				"Headers": {
						"Authorization":rawAuthorization
				 },
				"Domain": config.config_data.my_host,
				"Resource": "/auth/xxx/xxx"
		};


		var rawmyAuthResp = TykMakeHttpRequest(JSON.stringify(newRequest));

		var respObj = JSON.parse(rawmyAuthResp);

		if (debugMode) {
			log("raw MY auth response: " + rawmyAuthResp);
		}

		if (respObj.Code != 200) {
			request.ReturnOverrides.ResponseCode = 401;
			request.ReturnOverrides.ResponseError = 'MY Auth Failed: ' + respObj.code;
			return myAuth.ReturnData(request, {});
		}

		var expires_at = curr_epoch + parseInt(config.config_data.session_expires_seconds);

		if (debugMode) {
			log("curr_epoch="+curr_epoch + " new session expires_at:" + expires_at);
		}

		var newSession = {
			"expires": expires_at,
			"access_rights": {}
		};

		if (debugMode) {
			log("new session object = " + JSON.stringify(newSession));
		}

		TykSetKeyData(authHash, JSON.stringify(newSession));

		return myAuth.ReturnData(request,{});


	} else {

		var d = new Date();
		var curr_epoch = Math.round(d.getTime() / 1000);

		if (debugMode) {
			log("Pre-existing session exists... using, no MY auth check, curr_epoch: " + curr_epoch + " session.expires: " + session.expires);
		}

		return myAuth.ReturnData(request,{});
	}

});

log("====> myAuth initialised");

Disregard what I said - in that code you are checking expires and re-authing if the token is expired, so that should work fine as is and I wouldn’t change it and having the gateway check it would just result in access denied for the user.

Tyk will re-check the expires in the actual auth middleware but it will pass since you are rewriting it on re-auth.