I've been doing some research on implementing JWTs for a PHP based API we are building and one thing that confuses me the most at the moment are refresh tokens. From what I gather, you get both an access token and a refresh token during initial authentication and that the refresh token will allow you to basically skip this initial auth step to get you a fresh new access token when needed. If I understand this correctly, refresh tokens when generated need to be stored in a database paired with the client that just authenticated itself. If my access tokens only live for an extremely short amount of time (say 1 minute), does that mean that a very busy client using the API could end up querying my data store every minute to do the refresh step (to check if the refresh token exists/is still valid/has not been revoked/etc)? Wouldn't that be close to being just as bad as hitting my database with every request?
-
Are you talking about oAuth? – Karol Gasienica Oct 26 '16 at 18:19
-
Just JWTs and Refresh Tokens in general. Actually, I guess it's more of just a question about Refresh Tokens – georaldc Oct 26 '16 at 18:25
2 Answers
If your access tokens lives for a short time (1 min) you will need to generate a new one every minute, if of course user stays for longer than minute. Refresh tokens dependly of configuration can:
- Expire after first use
- Expire after given amount of time (f.ex. 14 days), so with one refresh token u can generate many access tokens
- Never expire, can only be revoked (f.ex. by generating a new refresh token)
In your case I think you can use Memcached to store for each user his own refresh token. But if may I ask, what's the reason, that your access token has to expire after 1 minute?
For example, first you can check if refresh token exists in your Memcached, and if not add it to Memcached and use it after it.
Example
<?php
$m = new Memcached();
$m->addServer('localhost', 11211);
$user_id = 1;
$refresh_token = $m->get($user_id."_refresh_token")
if (!refresh_token) {
if ($m->getResultCode() == Memcached::RES_NOTFOUND) {
$token = 'Some SQL query to get refresh token';
$m->set($user_id."_refresh_token", $token );
$refresh_token = $m->get($user_id."_refresh_token");
} else {
/* log error */
/* ... */
}
}

- 2,825
- 24
- 36
-
How would I force invalidate a refresh token if it's been cached? Would that not require constant checking of state everytime the refresh token is used? My thinking behind short access token life times was so that I could have scopes-changed-per-user take effect asap if needed. Isn't that one of the issues with access tokens that do not expire for a long period of time. – georaldc Oct 27 '16 at 16:00
-
My example shows if there is no token at all in memcached, but you can always overwrite key in memcached with a new token if current refresh token is failing some of your validators (f.ex. is expired or revoked). I think also about using JWT token as refresh token, it might work, because in JWT token are stored data such as expiration time, scopes, and other which you can define. Anyway you will need to always check access token when use. When it expires, or is invalid you can try to create new one, you can try do it once, when it fails again, you can just return false. – Karol Gasienica Oct 27 '16 at 20:09
The Access Token is like a DB cache for your user DB, and the expiry time is the TTL for that cache entry. Think of the expiry time on the Access Token as a heart beat of how often to validate the user against the user DB. If you get to high load on your user DB, you just increase the expiry time on your Access Tokens.
Your Refresh Token may be a JWT too, so you don't need to look that up in a DB/memcache. Normally when an Access Token expires, you check that the user account is not locked, that the user didn't changed the password etc. If everything looks ok you issue a new Access Token.

- 12,043
- 3
- 22
- 44