Revalidate authenticated routes in AdonisJs
Prevent users from using the back history to see authenticated pages after logging out
So, I recently started working on a project and I wanted to use it as an opportunity to learn a new framework. I decided on AdonisJs.
“ AdonisJs is a Node.js web framework with a breath of fresh air and drizzle of elegant syntax on top of it. We prefer developer joy and stability over anything else.” — AdonisJs
- It’s Node.js
- It implements the MVC structure (Model, View, Controller) which makes it really easy to organise your code.
- It’s gaining a lot of attention and I wanted to see what the fuss is all about.
So I came across a slight issue, and this is just a small tip that could help
Problem
Let’s say a user logged out from their dashboard, on pressing the back button the browser, the user can still see the contents of the authenticated page even when they have been logged out until the browser is closed. This poses a security issue because if the user should log out thinking all is well and good, another person can come in, click the back button and have access to the information on the authenticated page.
This happens because modern browsers tend to cache its pages so it doesn’t have to reload to get content, so it’s left for you to decide if you want to prevent this or not as it can affect the user experience.
I’ve noticed this issue also in Laravel and the solution here should work fine for both frameworks (and other frameworks too, I guess).
Solution
So what you want to do is set the response headers. This is best done using a middleware. In the root directory, open your console, type…
$ adonis make:middleware MustRevalidate
This will create a MustRevalidate.js
file in your Apps/Middleware
directory
Then replace the code in there with this
'use strict'class MustRevalidate {async handle({ request, response }, next) {// call next to advance the request// add headers to responseresponse.header('Cache-Control', 'nocache, no-store, max-age=0, must-revalidate')response.header('Pragma', 'no-cache')response.header('Expires', 'Fri, 01 Jan 1990 00:00:00 GMT')await next() }}module.exports = MustRevalidate
So all we’re doing is setting a couple response headers that will be sent back to the browser. It tells the browser that the page has already expired and it prevents the browser from caching the page.
Then you would want to register this middleware, open the kernel.js
in the start directory and register the middleware.
Registering it as global middleware is fine if you don’t want the browser to cache any of your pages but this isn’t really ideal in my opinion, what you want to do is add the middleware to authenticated pages that contain personal data.
Find the namedMiddleware
object and append the middleware like this
...
revalidate: 'App/Middleware/MustRevalidate'
}
...
Now we can add this middleware to any routes you want the browser to revalidate. For example,
Route.get('profile', 'UserController.profile').middleware('revalidate')
The browser will refresh the profile page every time it is accessed to prevent back history navigation.
Conclusion
So you can see it’s a pretty nifty tip for a problem you probably didn’t know you had, security should always be in mind when building for customers. This can also work for other frameworks or languages just by setting the response headers.