It creates an unrecoverable condition for the end user, here’s an example:
You issue Bob a token
Bob, being in a hurry, embeds this token into his application in a non-configurable way
Bob’s company uses the app
Bob leaves the company
The key expires
The key is deleted
The company bob used to work for can’t edit the token, so they ask you to renew it
You can’t because it is deleted, and need to generate a new one, which the company can’t use
It’s an extreme example, but it’s better to have an expired key you can manage than no key at all.
If the key is not deleted, then yes, it hangs around unused and clutters up your DB, but tokens are really really cheap in terms of memory, so you’re not going to run out any time soon. If you set an eviction policy in Redis, then they will be purged anyway if they are really unused for a long period of time.
Secondly, session timeouts AFAICR do not extend TTL on use, they are fixed, so act as a maximum lifetime for a token, even if the expiry date is beyond the timeout.
Our problem it’s that we associate a concurrent product license to this key, and if the event isn’t dispatched when expired ‘and not reused’ (because the user don’t logout and close the browser) this license it’s taken forever and don’t get released.
In this case, we need to implement some garbage collection for this keys that don’t send a ‘KeyExpired’ event…
It isn’t feasible to monitor millions of keys to dispatch events on expiry, which is why the feature doesn’t work the way you would like it to for your very specific use case. Even Redis, which has keyspace monitoring event dispatch, has a disclaimer saying that these events can dispatch a long time after TTL, so it’s not reliable.
There’s two other ways of doing this though:
The expires value that is set in the token is a unix timestamp, so if you are generating tokens programatically, then you can always implement your own clock.
Alternatively, add a heartbeat to your webapp that uses the key (it could just call a virtual endpoint, so you won;t need to implement anything server side), when the key expires, the heartbeat will fail with an assertable error and you can expire the concurrent license.
We reuse the key when the same user logins again, but the concurrent licenses need to be shareable between the same company users…
Maybe this will be the best approach to solve the problem…
The virtual endpoints don’t call middleware scripts ?
Because we have implemented a refresh expiry time every API access.
The middleware will run, so that’s not an option in your case then. Instead, maybe set up a new API, with a virtual endpoint for the heartbeat and bundle that API as part of the policy given to the keys (so they all have access), the new API won’t have any middleware scripts and so will just validate the expiry time on the token.
We decide to recheck all the company licenses (keys) assigned, every time we run-out of concurrent licenses for a company, and then free the non used locked ones.
I think it’s the lower cost operation we can do.
Thanks Martin, another time, for your excellent support.