Remember-me like behaviour with JWT

Michael Zangerle
Fusonic
Published in
3 min readAug 12, 2021

In a new project we are using Sylius headless and also their new api which uses JWT tokens to authenticate. Our customer wanted a remember-me like behaviour which people are used to. So the question is, how do we get such a behaviour with JWT tokens in Sylius?

Refresh tokens

As the tokens are self-contained and cannot be revoked it’s recommended that they are short-lived. To prevent a user from having to reauthenticate again and again there exists this https://github.com/markitosgv/JWTRefreshTokenBundle bundle which provides a refresh token in addition to the JWT token. This refresh token can be used to request a new valid JWT token. The refresh token itself can only be used for that process and can also be revoked if needed. For this to work the user has to be regularly online and the client has to implement a logic to get a new JWT token regularly. If that’s the case for your project then you should go with this approach.

What we were trying to achieve was the possibility to have two slightly different TTLs (Time-to-Live) for the JWT tokens (e.g. 1 day and 30 days). Some users might be online every day, some only every few weeks and some even less. The tokens shouldn’t be valid forever, but we wanted to provide a certain level of comfort by not having to re-authenticate every time the majority of users visits the shop. Revoking a token or disabling a user would also result in the same amount of work and we didn’t want to introduce all this complexity with refresh tokens just for that. So what to do?

Cookies

Sylius uses the lexik/LexikJWTAuthenticationBundle bundle for the whole JWT logic and this is pretty well documented. So we decided to switch to JWT via cookies as a first step. This removes the need to keep the token on the client side with easy access through JS and instead store it in a cookie. That’s still on the client obviously but now it’s possible to make it more secure by setting httpOnly and secure to true and samesite. This done by a few lines of configuration:

Remember-me

To get a remember-me like behaviour we would need to have two different TTLs for those tokens (and cookies) depending on the decision of the user. Did the user check the remember-me checkbox then the longer TTL should be used, otherwise the default.

So let’s create some class that provides the right TTL based on the request first and let’s call it TtlProvider. Nothing fancy there. The getTtl function returns the right TTL depending on the request body.

Now let’s make use of the new TtlProvider and integrate it with the LexikBundle. The easiest way to integrate it seems to be to add an event subscriber and override it there (thanks @chalasr). This could look similar to this:

We also have to align the cookie lifetime with the token lifetime as we wouldn’t want them to diverge. This can be done by decorating the JWTCookieProvider and using our TtlProvider there again.

In a last step we have to configure everything in our services.yaml:

That’s it. Now if you send a login request with rememberMe:true in the payload the longer TTL will be used and in all other cases the shorter one.

--

--

Michael Zangerle
Fusonic
Writer for

backend developer from Austria mostly working with PHP and Symfony // software architecture // continuous improvements // legacy code // self improvement