Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

lara75539's avatar

Determine whether user is allowed to enter route (Laravel, JWT, VueRouter)

Hi community.

For the first time I'm trying out Laravel and Vue together, and I've watched some series here on Laracasts despite the fact that some of the series is a bit outdated. Gave me a good insight.

Right now I'm struggling around how to determine whether the user is allowed to enter a page.

I have this snippet that runs before the VueRouter is entering a page (right now is userIsAuthenticated hardcoded to false for testing purposes):

router.beforeEach(async (to, from, next) => {
  const userIsAuthenticated = false
  
  if (to.matched.some(record => record.meta.requiresAuth)) {
    if (!userIsAuthenticated) {
      return next({
        path: '/login',
        params: { nextUrl: to.fullPath }
      })
    }

    return next()
  } else {
    if (userIsAuthenticated && to.name === 'login') {
      return next({
        path: '/',
        params: { nextUrl: to.fullPath }
      })
    }

    return next()
  }
})

On some pages I have several API calls, that requires authentication (Bearer token from JWT) - in that case I can redirect back to the login page, if the status code is either 401 or 403.

But what if I don't have any API calls requiring authentication on a page that requires that you are logged in? In this way I can't grab the JWT from my storage and classify it as valid proof of authentication, because the client side does not know anything about it's validity. How do I handle this scenario?

I've thought of some kind of "verification" endpoint, to check the tokens validity, every time the user navigates to a new page. But I think this as some kind of overhead or unnecessary complexity. I just can't get my head around any other solutions.

I'm not that skilled in Vue/JavaScript yet - so maybe there is some kind of standard way of handling this. But I can't Google me to it.

Thanks in advance

0 likes
10 replies
bobbybouwmann's avatar

Normally when you retrieve a JWT for authentication you get the token itself, but also an expired_at timestamp. You can use this timestamp to determine if the user needs to be login again or not. You can save this in your storage as well ;)

lara75539's avatar

That is a good point @bobbybouwmann. Do you know if that is the way to do it?

I mean... let's say it's all stored in localStorage - then some more or less technical people would be able to manipulate it easily, and get access.

:)

bobbybouwmann's avatar

Well, every developer could also adjust your javascript and perform some other action. So there is no way to really prevent this.

The only thing you can do is redirect the user to the login page if it's expired. If someone updates the data in localStorage your server should always catch this anyway, because the token is expired and it will force the user to log in again anyway.

I don't really see a thread here, to be honest. Your server is the only source of truth. Just checking on the date in localStorage makes it easier to see if a user is logged in or not. If someone tampers with the data in localStorage they probably expect weird results anyway.

willvincent's avatar

@sunedall not if you've properly included validation on the backend ... this is the fundamental drawback of SPAs, you cannot avoid duplicate logic between the front/backend for routing and authentication..

But whatever, always always ALWAYS do validation of everything on the backend. client-side validation should be considered at best a noise filter, and/or just the preliminary line of defense. Expect that anything and everything can and will be changed in javascript, and implement backend protections accordingly.

lara75539's avatar

Thanks @willvincent and @bobbybouwmann.

I follow your points. Of course I will not rely only on client side since it’s completely uncontrollable for me :-)

But if I have a restricted page without any API calls - just with hardcoded data... it will become impossible to handle properly right?

Would the solution be an endpoint, that checks/verify the token before entering each restricted page (like I suggested in my original post)?

Thanks for the inputs :-)

willvincent's avatar

I can't really think of a good reason to have a static page, that requires authentication, that isn't gonna hit the DB for anything

As for an endpoint.. just have something that verifies the user is authenticated and return true/false or return the user object or whatever.. doesn't seem like a difficult problem to solve

lara75539's avatar

Thank you @willvincent. I guess my setup is enough then, using the JWT middleware on my API endpoints.

That way the user will be forced to provide the token, be validated (or not) and be redirected to the login page (perhaps via an axios interceptor) again if JWT throws a validation error on the backend side and therefor respond with either 403 or 401.

I might have overthinked and overcomplicated the whole thing... πŸ€”πŸ˜Š

Side question: If you have done something similar to this before, where do you store the user's token? I keep reading that localStorage is a no go - but also I don't want to implement state with e.g. Vuex.

willvincent's avatar

In my current production app the JWT token (and reset token) are stored in vuex, and persisted to localstorage. On any given request if the token has expired the response is a 401, which is caught by an axios interceptor and automatically triggers an attempt to refresh the token, assuming that succeeds the initial request refires, if token refresh fails user is kicked over to the login screen.

This particular app is backed by adonis, not laravel.. adonis is more or less laravel, in javascript.

Laravel does tokens a little differently by default, whereas adonis' token implementation has the notion of a long-lived refresh token out of the box in addition to the short-life jwt token. Those long-lived tokens can be invalidated at the server side. Not sure what it would take to implement the same sort of setup in laravel off hand, but it's worked quite nicely for my current app. I routinely see 401 responses when tokens expired, and like magic it all just rights itself by auto-refreshing, and then submitting the requests again.. seamless & invisible to users.

bobbybouwmann's avatar

@willvincent You can implement the same setup as adonis using Laravel Passport. But indeed just using an interceptor should already work in most cases.

However, the question was about checking it without doing an API call. The only thing that works is then checking on the expired timestamp of the token. Laravel Passport gives this back by default.

1 like
willvincent's avatar

The only way to guarantee validity is to make that api call.. so if it's really gotta be restricted to authenticated users, the api call should be considered necessary.

Please or to participate in this conversation.