Gracefully Checking and Handling An Expired Auth Session

In this lesson, we’ll take a look at how to gracefully reset the user’s stale session, which includes authentication, CSRF tokens, or anything else you may have set for the user.

Published
Jun 18, 23
Duration
6m 22s

Developer, dog lover, and burrito eater. Currently teaching AdonisJS, a fully featured NodeJS framework, and running Adocasts where I post new lessons weekly. Professionally, I work with JavaScript, .Net C#, and SQL Server.

Adocasts

Burlington, KY

Prerequisites

This lesson is for session-based applications. If you’re using OAT or JWT tokens, this lesson will not be applicable to you.

When Does This Happen?

Let’s say a user is logged into our site and becomes preoccupied with something else, returning to our site several hours later. Within those passing hours, our system has logged out the user due to inactivity; however, since the user has been inactive the page is still displaying the same information as they left it.

Meaning, when they return, it’ll appear to them as though they’re still logged in.

Today’s Approach

Today we’ll be discussing how to remedy this by checking the user’s session when they return back to our site. Please note, if your application deals with sensitive information, like banking, you’ll want to utilize a more immediate approach than the one we’ll be covering here today.

Checking The User’s Session

First, we’ll need an API endpoint that will allow us to check the user’s session.

Route.get('/api/user/check', 'UsersController.check').as('api.user.check')
Copied!
  • start
  • routes.ts

In this example, all we’re worried about is checking the user’s authentication status, so we’ll just be returning whether the user is still authenticated.

public async check({ auth }: HttpContextContract) {
  return !!auth.user
}
Copied!
  • app
  • Controllers
  • Http
  • UsersController.ts

Knowing When A User Returned

Next, we’ll need to know when a user has returned to our site, we can easily do this by utilizing the browser’s onfocus event. Within this event, we’ll want to utilize our api.user.check route to check our user’s session.

window.onfocus = async function () {
  const { data: isAuthenticated } = await axios.get('/api/user/check')
  
  if (window.isAuthenticated && !isAuthenticated) {
    window.location = '/go/auth/reset'
  }
}
Copied!
  • resources
  • js
  • app.js

It is recommended to only perform this style of check when a user actually performs an action, in our case that action is returning to the site, because otherwise, you may inadvertently prevent their session from expiring due to inactivity.

Inside our layout, let's also set a global variable holding whether the user is authenticated at the time our page initially loaded. As you can see we’ll be using this above to determine if our user has been logged out due to inactivity.

<script>
  window.isAuthenticated = {{ !!auth.user }}
</script>

// note, in the video I'm adding this to a site using Unpoly
// therefore, I'm adding this onto my up-main element via
// the x-init attribute provided by AlineJS
<div x-data="{}" x-init="window.isAuthenticated = {{ !!auth.user }}" up-main>
  {{-- page contents --}}
</div>
Copied!
  • resources
  • layouts
  • app.edge

Handling An Invalidated Session

Lastly, you’ll see that if the two isAuthenticated variables don’t match within our onfocus handler, we’re forwarding the user to a /go/auth/reset page.

Route.get('/go/auth/reset', 'GoController.authReset').as('go.auth.reset')
Copied!
  • start
  • routes.ts

This page will simply alert the user their session has been invalidated and kick them back to the page they were on before.

public async authReset({ response, session }: HttpContextContract) {
  session.flash('warning', 'Your session has expired.')
  return response.redirect().back()
}
Copied!
  • app
  • Controllers
  • Http
  • GoController.ts

Note, if your user was on an auth-protected page at the time their session was invalidated, your auth middleware will divert the user away from that page to whatever page you have set within your middleware. In my case, it’s my login page.

In addition to this, if you have followed our lesson on redirecting a user back to their previous page after login, they’ll be returned back to their auth-protected page once they do log back in; making this a very seamless flow.

Simplifying Testing

We should now be all set up, however, by default an AdonisJS session stays valid for two hours without activity. Let's drop that down to a minute or two so we don’t have to sit and wait to ensure everything is working.

export default sessionConfig({
  // ...

  age: '1m', // '2h', 

  // ...
})
Copied!
  • config
  • session.ts

Join The Discussion! (0 Comments)

Please sign in or sign up for free to join in on the dicussion.

robot comment bubble

Be the first to Comment!